How to find an ArrayCollection item with a specific property value?
Solution 1
No, you can't. struct.mi.(@id == "2").@stuff
is E4X which is short for ECMA Script for XML. You can't use e4x on other AS objects.
Solution 2
You can generalize Matt's answer a bit so that you can pass in the ID value you want instead of hard-coding it, and only need a single line to get your match (I assume you may want to do this in multiple places).
First you'd write a function to generate your find function:
function findId(id:int):Function {
return function( element : *, index : int, array : Array ) : Boolean
{
return element.id == id;
}
}
Then I'd write a function to return the first match so you don't have to duplicate the two lines:
function findInCollection(c:ArrayCollection, find:Function):Object {
var matches : Array = c.source.filter( find );
return ( matches.length > 0 ? matches[0] : null );
}
Then you'd just do this:
var stuff:String = findInCollection(cmenu, findId(2)) as String;
Solution 3
I've always used filterFunctions for ArrayCollections:
private var cmenu:ArrayCollection = new ArrayCollection([
{id:"1", stuff:"whatever"},
{id:"2", stuff:"whatever"},
{id:"3", stuff:"whatever"}
]);
function getItemFromCollection(id:String):Object {
var cmenuFiltered:ArrayCollection = new ArrayCollection(cmenu.toArray());
cmenuFiltered.filterFunction =
function(item:Object):Boolean {
return item.id == id;
}
cmenuFiltered.refresh();
return cmenuFiltered.getItemAt(0);
}
Solution 4
If you look at the docs for the Array class, you'll find several routines that aid in this, but none as concise as the e4x syntax used by the built-in XML data type. The filter()
method in particular sounds like it might be the best fit for your example.
Here's a sample for how you might do this, given your setup.
var matches : Array = cmenu.source.filter( findId2 );
var stuff : Object = ( matches.length > 0 ? matches[0] : null );
...and the callback function findId2
:
function findId2( element : *, index : int, array : Array ) : Boolean
{
return element.id == 2;
}
Solution 5
You can actually go a little bit further and roll the filter function up into the findInCollection
function. This means you can just pass the ArrayCollection, property name, and value in the same call:
public function findInCollection(c:ArrayCollection,
propertyName:String, propertyValue:*):Array {
var matches : Array = c.source.filter(
function( element : *, index : int, array : Array ) : Boolean {
return element[propertyName] == propertyValue;
}
);
return matches;
}
var ac:ArrayCollection=new ArrayCollection(
[{name:'Ben', id:1, age:12},
{name:'Jack', id:2, age:22},
{name:'Jill', id:4, age:22},
{name:'Joe', id:3, age:17}
]
);
var searchedElements:Array=findInCollection(ac,'age',22);
Returns an array containing the 'Jack' and 'Jill' objects.
Obviously this only works if you are looking for a single property value, but if you wanted to search on multiple properties it would be possible to pass through an object containing the properties and values to search for.
Giorgio Gelardi
Updated on July 05, 2022Comments
-
Giorgio Gelardi about 2 years
I have some XML structures like this:
var struct:XML = <mh> <mi id="1" stuff="whatever"/> <mi id="2" stuff="whatever"/> <mi id="3" stuff="whatever"/> </mh>;
I know I can access a subnode by "id", in this way:
var stuff:Object = struct.(hasOwnProperty('@id') && @id == '2').@stuff;
Now I have some similar ArrayCollection structure:
private var cmenu:ArrayCollection = new ArrayCollection([ {id:"1", stuff:"whatever"}, {id:"2", stuff:"whatever"}, {id:"3", stuff:"whatever"} ]);
I wonder if items can be accessed in a similar way, like this:
var stuff:Object = cmenu['id == 2'].stuff;
Is it possible?
-
Matt Dillard over 14 yearsWow, neat use of that function factory. I've always felt there must be a way to customize the callback routine; this is really elegant.
-
Eric Belair over 14 yearsWhy not be helpful, and actually show the user the right way to do it, rather than simply telling them "No, you can't"?
-
Amarghosh over 14 yearsWhen I saw this thread, there were answers explaining how to do it - why would I do that again? But I thought it would be good to let OP know why the "@syntax" was not possible on array collections and other AS objects in general. And apparently OP was "wondering if items can be accessed in a similar way" - so a "no" along with "why not" seemed a good answer.
-
Pimenta about 12 yearsThis has been very useful for me since Array Collections are not as straight forward in Flex/AS3 as in other languages. Thanks @Herms for your simple solution on this. I'm using it for an XML service with local file.
-
tigeryan over 11 yearsVery useful and very quick on large collections! Thanks much!
-
adarshk over 10 yearsvery optimized way for large Array Collections.