【问题标题】:Flash as3 How do I remove duplicates in an array?Flash as3 如何删除数组中的重复项?
【发布时间】:2011-08-25 06:21:40
【问题描述】:

您好,我在 flash 中只有一个名称(字符串)数组,我想确保删除数组中的所有重复项,或者至少确保数组中每个重复出现的值只执行一次函数。

【问题讨论】:

    标签: flash actionscript-3 actionscript


    【解决方案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 的方法可能效率更高,但这是您要求的理论:)

                【讨论】:

                  猜你喜欢
                  • 2017-11-12
                  • 2017-06-21
                  • 2022-01-03
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-10-04
                  • 2014-06-07
                  • 2019-07-11
                  相关资源
                  最近更新 更多