views:

585

answers:

4

Hi,

I have an ArrayCollection as mentioned below.

        private var initDG:ArrayCollection = new ArrayCollection([
            {fact: "Order #2314", appName: "AA"},

            {fact: "Order #2315", appName: "BB"}

            {fact: "Order #2316", appName: "BB"}
                            ...

            {fact: "Order #2320", appName: "CC"}

            {fact: "Order #2321", appName: "CC"}

            ]);

I want to populate a ComboBox with UNIQUE VALUES of "appName" field from the ArrayCollection initDG.

<mx:ComboBox id="appCombo" dataProvider="{initDG}" labelField="appName"/>

One method I could think is to loop through the Array objects and for each object check and push unique appName entries into another Array. Is there any better solution available?

+1  A: 

That sounds good to me:

var unique:Object = {};
var value:String;
var array:Array = initDG.toArray();
var result:Array = [];
var i:int = 0;
var n:int = array.length;
for (i; i < n; i++)
{
 value = array[i].appName;
 if (!unique[value])
 {
  unique[value] = true;
  result.push(value);
 }

}
return new ArrayCollection(result);
viatropos
hey this worked great for me! cheers!
Devtron
A: 

Alas, there is no unique() method in ActionScript's Array, but you can approximate it like this:

var names:Array = initDG.toArray().map(
    function (e:Object, i:Number, a:Array):String {
        return e.appName;
    }
);

var uniqueNames:Array = names.filter(
    function (name:String, i:Number, a:Array):Boolean {
                // Only returns true for the first instance.
        return names.indexOf(name) == i;
    }
);

Note this happens to work because you are filtering strings, which are compared by value. This wouldn't be effective if you needed to filter arbitrary objects.

lach
the only issue with those is that anonymous functions come at a huge performance cost: http://gskinner.com/talks/quick/#52, and `array.indexOf` requires you iterate over the array internally each call, which is expensive.
viatropos
How many elements do you intend to have in there?
lach
That's an excellent presentation that you referenced. Very interesting. I didn't realise that anonymous function calls were so much more expensive than direct method invocations. But the results in that chart are for 100,000 invocations. This code block requires 2 invocations on an anonymous function. So, unless you're going to iterate over this thousands of times to populate your combo-box, I hardly think the performance cost is going to be "huge". Code readability is more important than salvaging a couple of cycles, unless there are noticeable performance problems.
lach
Also, your comment about having to iterate the array for each comparison also applies to your original suggestion of storing the unique values in a second array. It might be faster if you used a Dictionary. But again, unless the size of your collection is huge there will probably not be any noticeable performance issue. When you asked for a 'better' solution, was it performance you were concerned about?
lach
I misspoke. The functions are invoked for every element in the collection. However, they are only passed once. Inside the map function, they are stored as local variables, so the performance should be as per reference invocations, not anonymous invocations.
lach
nice, that's good to know. I just always try to choose the most optimized solution, as long as it's just as easy, even if it's only 2 iterations, so I can stay in the habit of.
viatropos
A: 

you can used this class for finding unique arraycollection tempArray=_uniqueArray.applyUnqiueKey1(_normalsearchdata.toArray());

"uniqueArray" this is package name and _normalsearchdata is ArrayCollection;

package{ import mx.collections.ArrayCollection; public class applyUniqueKey{ private var tempArray:Array;

    private var tempIndex = 0;
    public var temp:String;
    public function applyUnqiueKey1(myArray)

    {
        tempArray = new Array();
        tempIndex = 0;  
        myArray.sort();
        tempArray[0] = myArray[0];
        tempIndex++;

        for(var i=1; i<myArray.length; i++) {
            if(myArray[i] != myArray[i-1]) {
                tempArray[tempIndex] = myArray[i];
                tempIndex++;
            }
        }
        var temp=String(tempArray.join());
        return new ArrayCollection(tempArray);
    }
}

}

Vijay

vijay