我有一组具有不同属性的对象,我需要以不重复特定属性的方式过滤数组。
例如:
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
具有相同值的那些对象也不会成为结果数组。
对象数组用作数据提供者,用{(1}}填充有关聊天室的信息。数组中的对象携带相关信息(如服务器上的房间ID和其他一些配置设置)。
我在示例中使用的s:Datagrid
属性实际上是聊天室配置使用的语言的ID,我想创建一个baz
,我可以使用s:DropDownList
来过滤Datagrid
对于单个语言(例如,显示所有使用"德语")的房间。
很可能有很多具有相同语言ID的对象,但我只希望每个语言ID在DropDownList
中显示一次。
我需要从Datagrids's
数据提供者(源数组)中提取该信息,并且无法直接检索我的语言,因为DropDownList
是许多中使用的泛型DatagridHeaderRenderer
的一部分具有不同数据的不同Datagrids
。
答案 0 :(得分:2)
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
答案 1 :(得分:1)
表面看起来应该有效。使用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);
}