1

我有一组具有不同属性的对象,我需要以不重复特定属性的方式过滤数组。

例如:

var array:Array = [{foo:"a1", bar:"b1", baz:"c1"},
                   {foo:"a2", bar:"b2", baz:"c2"},
                   {foo:"a3", bar:"b1", baz:"c3"},
                   {foo:"a1", bar:"b4", baz:"c2"},
                   {foo:"a0", bar:"b3", baz:"c1"}];

现在假设我想过滤属性上的对象baz。过滤数组的最有效方法是什么,以便baz在操作后没有两个元素具有相同的值?

在我的示例中,结果应仅包含:

var result:Array = [{foo:"a1", bar:"b1", baz:"c1"},
                    {foo:"a2", bar:"b2", baz:"c2"},
                    {foo:"a3", bar:"b1", baz:"c3"}]

因为其他对象将具有该baz属性的重复条目。

结果数组的顺序并不重要,具有相同值的对象中的哪个对象进入结果数组也不重要baz


更新:

对象数组用作数据提供者来填充s:Datagrid有关聊天室的信息。数组中的对象携带相关信息(如服务器上的房间 ID 和其他一些配置设置)。

baz我在示例中使用的属性实际上是聊天室配置为使用的语言的 ID,我想创建一个s:DropDownList用于过滤Datagrid各个语言的 ID(例如,显示所有使用“德语”的房间)。

很可能有许多具有相同语言 ID 的对象,但我只希望每个语言 ID 在DropDownList.

我需要从数据提供者(源数组)中提取该信息,Datagrids's并且无法直接检索我的语言,因为它是用于许多不同数据DropDownList的泛型的一部分。DatagridHeaderRendererDatagrids

4

2 回答 2

1
private var array:Array = [{foo:"a1", bar:"b1", baz:"c1"},
               {foo:"a2", bar:"b2", baz:"c2"},
               {foo:"a3", bar:"b1", baz:"c3"},
               {foo:"a1", bar:"b4", baz:"c2"},
               {foo:"a0", bar:"b3", baz:"c1"}];

private var filteredArray:Array;
private var keys:Object = {};

private function filterArray():void{
    filteredArray = arr.filter(removeDupes);
}

private function removeDupes(item:Object, idx:uint, arr:Array):Boolean {
    if (keys.hasOwnProperty(item.baz)){
        return false;
    } else {
        keys[item.baz] = item;
        return true;
    }
}

private function resetFilter():void{
    filteredArray = new Array();
    keys = {};
}

从多个来源修改但主要是:http: //blog.flexexamples.com/2007/08/05/removing-duplicate-items-from-an-array-using-the-arrayfilter-method/

或者您可以只使用 arrayCollection 及其内置的 filterFunction。请参阅:http ://cookbooks.adobe.com/post_Using_the_to_ArrayCollection_s_filterFunction-5441.html

于 2012-05-09T09:42:29.633 回答
0

从表面上看,它应该可以工作。使用 Array.filter 通常是在循环中执行相同操作的时间的两倍。

我认为'Dom 的removeDupes函数并不能完全满足要求,尽管它可能是一种更通用的方法(例如,如果===不是一个好的比较函数,那么这为您提供了一种扩展它的方法。)但是使用hasOwnPropery是一个很大的禁忌。你永远不应该碰它——这个功能只存在于 ES 兼容性。否则它是邪恶的 - 潜在的安全漏洞(因为它被定义Object.prototype,因此很容易为外部代码覆盖)并且速度很慢(出于同样的原因 - 在原型上定义的函数的查找比在原型上定义的函数要慢一类)。

    public function Test()
    {
        super();
        var array:Array = [{foo:"a1", bar:"b1", baz:"c1"},
            {foo:"a2", bar:"b2", baz:"c2"},
            {foo:"a3", bar:"b1", baz:"c3"},
            {foo:"a1", bar:"b4", baz:"c2"},
            {foo:"a0", bar:"b3", baz:"c1"}];
        this.removeDuplicates(array, "baz").map(this.objectTracer);
        // { foo : a3, baz : c3, bar : b1 }
        // { foo : a1, baz : c2, bar : b4 }
        // { foo : a0, baz : c1, bar : b3 }
    }

    private function objectTracer(object:Object, index:int, all:Array):void
    {
        var result:String = "";
        for (var p:String in object)
            result += ", " + p + " : " + object[p];
        if (result) result = result.substr(2);
        trace("{ " + result + " }");
    }

    private function removeDuplicates(array:Array, on:String):Array
    {
        var result:Array = array.concat();
        // note that since we use `Dictionary' the 
        // the comparison between objects is the same as `==='
        // if all values are strings, you can use `Object' to
        // save some space.
        var hash:Dictionary = new Dictionary();
        var temp:Object;

        for (var i:int, j:int = result.length - 1; j >= i; j--)
        {
            temp = result[j][on];
            if (temp in hash)
            {
                result[j] = result[i];
                j++; i++;
            }
            else hash[temp] = true;
        }
        // note that we could `shift()` until we get to `i'
        // but when we do it, we actually reallocate the array every time
        // so `slice()' must, in theory, be more efficient
        return result.slice(i);
    }
于 2012-05-09T10:38:44.980 回答