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 如何删除数组中的重复项?的主要内容,如果未能解决你的问题,请参考以下文章

用flash as3语言如何将影片剪辑存入一个数组以及如何访问?

单击按钮时如何删除组合框组件 flash as3

FLASH AS3 二维数组如何查找某个元素的索引?

ActionScript 3 AS3:删除阵列中的重复项

flash AS3 如何删除舞台事件侦听器

如何从 Perl 中的数组中删除重复项?