Flash as3 如何删除数组中的重复项?
Posted
技术标签:
【中文标题】Flash as3 如何删除数组中的重复项?【英文标题】:Flash as3 How do I remove duplicates in an array? 【发布时间】:2011-08-25 06:21:40 【问题描述】:您好,我在 flash 中只有一个名称(字符串)数组,我想确保删除数组中的所有重复项,或者至少确保数组中每个重复出现的值只执行一次函数。
【问题讨论】:
【参考方案1】:好答案!
我检查了其中一些,与我的相比,它们的结果更差。 示例:
const origin: Vector.<String> = Vector.<String>(["a", "c", "d", "c", "b", "a", "e", "b", "a"]);
function getUniqueVector(origin: Vector.<String>): Vector.<String>
const n: uint = origin.length;
var res: Vector.<String> = new Vector.<String>();
var i: int = 0;
while(i < n)
var el: String = origin[i];
if(res.indexOf(el) == -1) res.push(el);
i += 1;
return res;
trace(getUniqueVector(origin)); // unique elements vector
我的数据统计:
字典方法:8946ms、8718ms、8936ms
Obj 方法:8800ms、8809ms、8769ms
我的旧方法:8723ms、8599ms、8700ms
这种方法:6771ms、6867ms、6706ms
2019 年 7 月 2 日更新
值得注意的是,为了获得更好的性能,创建对象,并将每个推送的值设置为 O(1) 复杂度检索的关键,因此结果会更好一些。
但是 Flash 已经死了,而且可能是 ActionScript,所以这是一个葬礼演讲 :(
【讨论】:
好答案!至于你的评论,你听说过Apache Royal吗?国王死了,皇家万岁!【参考方案2】:function removeDuplicateElement(_arr:Array):Array
//set new Dictionary
var lDic:Dictionary = new Dictionary();
for each(var thisElement:* in _arr)
//All values of duplicate entries will be overwritten
lDic[thisElement] = true;
_arr = [];
for(var lKey:* in lDic)
_arr.push(lKey);
return _arr;
【讨论】:
【参考方案3】:这是一种更优雅的删除重复项的方法:
var items:Vector.<String> = Vector.<String>(['tortoise', 'cat', 'dog', 'bunny', 'dog', 'cat', 'bunny', 'lion']);
var uniqueItems:Vector.<String> = items.filter(function(item:String, index:int, vector:Vector.<String>):Boolean
return index==0?true:(vector.lastIndexOf(item, index-1) == -1);
);
数组的相同方法:
var items:Array = ['tortoise', 'cat', 'dog', 'bunny', 'dog', 'cat', 'bunny', 'lion'];
var uniqueItems:Array = items.filter(function(item:String, index:int, array:Array):Boolean
return index==0?true:(array.lastIndexOf(item, index-1) == -1);
);
【讨论】:
【参考方案4】:这是一种方法,我相信还有其他方法。
function removeDuplicate(sourceArray:Array) : void
for (var i:int = 0; i < sourceArray.length - 1; i++)
for (var j:int = i + 1; j < sourceArray.length; j++)
if (sourceArray[i] === sourceArray[j])
// Remove duplicated element and decrease j index.
sourceArray.splice(j--, 1);
【讨论】:
这样就可以做到,但是在时间复杂度方面非常浪费,不是最好的解决方案。有很多方法不是 O(N^2)。究竟哪种解决方案最适合真实数据,在一定程度上取决于对欺骗频率的预期。 是的,同意。只是给他一个可以使用的概念。在任何情况下,您都可以选择不同的锤子。 但是,我想一个关于所有潜在锤子及其优缺点的教程可能是值得的。不过,我现在要把它传下去。 我把我的想法写进了我的帖子。我之前并没有费心实际编写代码,因为我在工作,但是如果数组有很多预期的重复,那么使用字典作为简单映射在时间上是一个 O(N) 解决方案,并且最多每个唯一条目的额外内存需要 1 个布尔值(远低于任何涉及将字符串复制到新数组的解决方案)。【参考方案5】:我投票支持 Adam 的选项,但后来我发现了这一点,而且在我看来,这可能是更好的性能吗?
for (var i:uint = array.length; i > 0; i--)
if (array.indexOf(array[i-1]) != i-1)
array.splice(i-1,1);
这里的想法是你在数组中向后循环,并且由于 indexOf 为你提供了第一个出现的索引,你可以用当前的 index(i) 检查找到的索引,如果不一样就删除。
【讨论】:
【参考方案6】:如果 sourceArray[i] 与 sourceArray[j] 匹配不止一次,@prototypical 的响应会不会出现问题,因为如果一个元素被 .splice()d 从中取出,sourceArray 的长度会更短?
我已经重写了这个方法,从末尾开始计数,这样就不会发生这种情况
for (var i:int = sourceArray.length - 2; i >= 0; --i)
for (var j:int = sourceArray.length - 1; j > i; --j)
trace(i, j);
if (sourceArray[j] === sourceArray[i]) sourceArray.splice(j, 1);
【讨论】:
【参考方案7】:更多猫皮:
var a:Array = ["Tom", "John", "Susan", "Marie", "Tom", "John", "Tom", "Eva"];
a.sort();
var i:int = 0;
while(i < a.length)
while(i < a.length+1 && a[i] == a[i+1])
a.splice(i, 1);
i++;
【讨论】:
【参考方案8】:很多方法。您可以对数组进行排序并对其进行迭代,而忽略与上一次迭代匹配的条目。或者您可以使用 indexOf() 搜索重复项。或者您可以遍历数组,构建一个以字符串为键的字典(并忽略已经有条目的键)。
这是字典方式,每个唯一条目的内存成本为 1 个布尔值,当您期望有很多欺骗时,内存成本很容易,而且速度很快。如果你的受骗者相对较少,那么对连续受骗者进行排序+剔除可能会更有效
import flash.utils.Dictionary;
var array:Array = ["harry","potter","ron","harry","snape","ginny","ron"];
var dict:Dictionary = new Dictionary();
for (var i:int = array.length-1; i>=0; --i)
var str:String = array[i] as String;
trace(str);
if (!dict[str])
dict[str] = true;
else
array.splice(i,1);
dict = null;
trace(array);
这是一种排序方式,但请注意:这不会保留顺序!你没有说这是否重要。但是因为它使用的是快速排序,所以它确实倾向于具有 O(N log N) 的性能以及额外的一次传递,除非您的数据当然是病态的情况。
var array:Array = ["harry","potter","ron","harry","ron","snape","ginny","ron"];
array.sort();
trace(array);
for (var i:int = array.length-1; i>0; --i)
if (array[i]===array[i-1])
array.splice(i,1);
trace(array);
除了没有说明顺序是否重要之外,您没有说明留下哪些欺骗是否重要:索引最低的那个,或者找到的最后一个。如果这很重要,您将需要重新排序我的字典示例以向相反方向运行。我从最后开始,因为这样可以在不使循环计数无效的情况下进行拼接(即通过在循环期间更改 array.length)如果顺序很重要,请按通常的正向循环并复制每个字符串的第一次出现到一个新数组,或者像这样修改循环计数器。这可能是我会使用的技术,因为它保留了顺序并保留了每个字符串的第一次遇到的实例:
import flash.utils.Dictionary;
var array:Array = ["harry","potter","ron","harry","snape","ginny","ron"];
var dict:Dictionary = new Dictionary();
var len:int = array.length;
for (var i:int = 0; i<len; ++i)
var str:String = array[i] as String;
if (!dict[str])
dict[str] = true;
else
array.splice(i,1);
i--; len--;
dict = null;
trace(array);
【讨论】:
【参考方案9】:这是另一种方法,可能看起来更好看:
var removeList:Array = [];
// loop over every item in the original array
for each (var item:* in array)
// loop over every item again, checking for duplicates
for each (var other:* in array)
// if two items that aren't the same item are equal and `other` doesn't
// exist in the remove list, then cache it for later removal.
if (item == other && item !== other && removeList.indexOf(other) == -1)
removeList.push(other);
// next, loop over the cached remove list and remove 'selected' items for removal
for each (var remove:* in removeList)
array.splice(array.indexOf(remove), 1);
这可能不是最高效的方法,@prototypical 的方法可能效率更高,但这是您要求的理论:)
【讨论】:
以上是关于Flash as3 如何删除数组中的重复项?的主要内容,如果未能解决你的问题,请参考以下文章