我有一些像这样的XML结构:
var struct:XML = <mh>
<mi id="1" stuff="whatever"/>
<mi id="2" stuff="whatever"/>
<mi id="3" stuff="whatever"/>
</mh>;
我知道我可以通过“id”访问子节点,这样:
var stuff:Object = struct.(hasOwnProperty('@id') && @id == '2').@stuff;
现在我有一些类似的ArrayCollection结构:
private var cmenu:ArrayCollection = new ArrayCollection([
{id:"1", stuff:"whatever"},
{id:"2", stuff:"whatever"},
{id:"3", stuff:"whatever"}
]);
我想知道是否可以以类似的方式访问项目,例如:
var stuff:Object = cmenu['id == 2'].stuff;
有可能吗?
答案 0 :(得分:18)
你可以稍微概括一下Matt的答案,这样你就可以传入你想要的ID值而不是硬编码,只需要一行来获得你的匹配(我假设你可能想在多个地方这样做) )。
首先,您要编写一个函数来生成查找函数:
function findId(id:int):Function {
return function( element : *, index : int, array : Array ) : Boolean
{
return element.id == id;
}
}
然后我会编写一个函数来返回第一个匹配项,这样你就不必重复这两行:
function findInCollection(c:ArrayCollection, find:Function):Object {
var matches : Array = c.source.filter( find );
return ( matches.length > 0 ? matches[0] : null );
}
然后你就这样做了:
var stuff:String = findInCollection(cmenu, findId(2)) as String;
答案 1 :(得分:4)
我总是将filterFunction用于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);
}
答案 2 :(得分:3)
如果你查看Array类的文档,你会发现几个有助于此的例程,但没有一个像内置XML数据类型使用的e4x语法那样简洁。特别是filter()
方法听起来可能最适合您的示例。
根据您的设置,以下是您可能会如何执行此操作的示例。
var matches : Array = cmenu.source.filter( findId2 );
var stuff : Object = ( matches.length > 0 ? matches[0] : null );
...和回调函数findId2
:
function findId2( element : *, index : int, array : Array ) : Boolean
{
return element.id == 2;
}
答案 3 :(得分:3)
struct.mi.(@id == "2").@stuff
是E4X,它是ECMA Script for XML的缩写。您不能在其他AS对象上使用e4x。
答案 4 :(得分:2)
您实际上可以更进一步,将过滤功能向上滚动到findInCollection
功能。这意味着您只需在同一个调用中传递ArrayCollection,属性名称和值:
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);
返回包含“Jack”和“Jill”对象的数组。
显然,这仅在您查找单个属性值时有效,但如果您想搜索多个属性,则可以通过包含要搜索的属性和值的对象。
答案 5 :(得分:0)
你可以通过在函数中添加属性名称来更加概括Herms答案,从而获得一种在ArrayCollection中按属性搜索的相当通用的方法
private function findInCollection(c:ArrayCollection, findFunction:Function):Array
{
var matches : Array = c.source.filter( findFunction );
return matches;
}
private function findFunction(propertyName:String,propertyValue:*):Function
{
return function( element : *, index : int, array : Array ) : Boolean
{
return element[propertyName] == propertyValue;
}
}
具有以下用途
var ac:ArrayCollection=new ArrayCollection(
[{name:'Ben', id:1, age:12},
{name:'Jack', id:2, age:22},
{name:'Joe', id:3, age:17}
]
);
var searchedElements:Array=findInCollection(ac,findFunction('id',2));
它将返回一个包含以下对象的数组
{name:'Jack', id:2, age:22}
此方法的缺点是我们使用String对属性名称进行硬编码。 这可能对代码维护有害。
答案 6 :(得分:0)
'private var cmenu:ArrayCollection = new ArrayCollection([
{id:"1", stuff:"whatever"},
{id:"2", stuff:"whatever"},
{id:"3", stuff:"whatever"}
]);
for(var i:int=0;i<cmenu.length;i++){
var num:Number=cmenu.getItemAt(i).id;
if(num==2){
var stuf:String=cmenu.getItemAt(i).stuff;
}
}'