如何查找具有特定属性值的ArrayCollection项?

时间:2009-10-14 13:11:57

标签: flex actionscript syntax

我有一些像这样的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;

有可能吗?

7 个答案:

答案 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;
}
}'