搜索和删除数组中重复的算法

时间:2013-07-29 20:37:48

标签: javascript arrays algorithm compare array-splice

我有一个数组,其中一些元素是“重复”,我想删除数组中的重复。

因此,例如,左侧的列表(数组)变为右侧的数组:

Ingredients:             Ingredients:
Apples                   Apples
Apples                   Oranges
Oranges                  Bananas
Oranges
Oranges
Bananas 

这样做的好算法是什么?

现在这就是我的伪代码

for each element in ingredients (counter j)
     for each element-below-current-element (counter k)
         if ingredients[i] == element-below-current-element[j]
             splice (delete) ingredients[i]

现在问题是我注意到原始列表中是否有奇数数量的元素,那么我可能会得到这样的结果:

Ingredients:             Ingredients:
Apples                   Apples
Oranges                  Oranges
Oranges                  Oranges
Oranges                  Bananas
Bananas

一切都有效,除了我可能会得到一种成分的双倍。

这是我的实际代码实现,在 javascript 中,并且包含一些角度元素(例如$ scope),但它并不重要。

    for(var j = 0; j < $scope.groceryList.length; j++){
        for(var k = j+1; k < $scope.groceryList.length; k++){ // for each of elements below current element (j)
            if ( $scope.groceryList[j].name == $scope.groceryList[k].name){
                $scope.groceryList.splice(k, 1);
                }
            }
    }

现在我得到的是每当你移除一个数组元素时数组长度是如何减少的,​​这会导致你的计数器在下一次迭代时向前跳一个元素...

8 个答案:

答案 0 :(得分:4)

Underscore.js是我推荐用于在JavaScript中执行所有数组处理的工具(还有,就像,就像所有内容一样。非常棒。)

恰好它的uniq方法将完全符合你的需要。

var myArray = ["Apples","Oranges","Oranges","Grapes","Apples"];
_.uniq(myArray);
//returns ["Apples","Oranges","Grapes"]

答案 1 :(得分:2)

在这种情况下,您通常无法使用for循环进行内循环。 while效果很好,但是:

for(var j = 0; j < $scope.groceryList.length; j++){
    var k = j+1;
    while(k < $scope.groceryList.length){ // each of elements below current element (j)
        if ( $scope.groceryList[j].name == $scope.groceryList[k].name){
            $scope.groceryList.splice(k, 1);
            }
        else {
            ++k;
            }
        }
}

如果您拼接,请不要增加k。如果你不这样做,那就去做吧。

(我希望我的缩进是正确的,它不是我以前习惯的风格。)

答案 2 :(得分:1)

我只是对它进行排序,然后进行比较......

var arr = ["Apples","Oranges","Oranges","Grapes","Apples"];
 var sorted_arr = arr.sort(); 

  var results = [];
  for (var i = 0; i < arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
    results.push(sorted_arr[i]);
  }
 }

alert(results);

答案 3 :(得分:1)

此代码是最简单的解决方案,但需要双倍的内存 - 对于示例中的小数据集而言不是问题。

Array.prototype.filterDuplicates = function () {
    var filtered = [];
    for (var i = 0; i < this.length; i++)
        if (filtered.indexOf(this[i]) == -1)
            filtered.push(this[i]);
    return filtered;
}

答案 4 :(得分:1)

我最喜欢的方法是使用数组方法来保存代码:

arr1=[
    "Apples",
    "Apples",
    "Oranges",
    "Oranges",
    "Oranges",
    "Bananas"
];


var unq= arr1.filter(function unq(a,b,c){return c.indexOf(a)===b;});

alert(unq); // shows "Apples,Oranges,Bananas"

没有变量,没有工件,只有逻辑和结果。

编辑:更改为仅使用一个重复数组。 如果你想从另一个数组中过滤一个数组,只需将上面的“c.indexOf”更改为数组的var名称。

我更喜欢打破unq功能,所以我可以从任何地方调用.filter(unq)来获得一个独特的数组......

答案 5 :(得分:1)

线性时间,恒定空间算法:

  1. 有两个指数(一个快速和一个慢),都从零开始
  2. 增加两个元素直到前一个元素与当前元素相同
  3. 增加快速值,直到找到不同的元素
  4. 将慢索引处的元素设置为快速索引处的元素
  5. 增加两者
  6. 增加快速值,直到与替换元素不同
  7. 从4开始重复,直到快速结束。
  8. 将列表缩短为短篇
  9. 不,我不能给你JavaScript。

    示例:

    输入:

    Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
    

    有两个指数(一个快速和一个慢),都从零开始

       fast
       slow
         V
    Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
    

    增加两者直到我们前一个元素与当前元素相同。

                         fast
                         slow
                           V
    Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
    

    快速增加直到它不同。

                         slow     fast
                           V        V
    Ingredients, Apples, Apples, Oranges, Oranges, Oranges, Bananas
    

    快速将元素设置为缓慢的元素。

                         slow      fast
                           V         V
    Ingredients, Apples, Oranges, Oranges, Oranges, Oranges, Bananas
    

    增加两者。

                                   slow     fast
                                     V        V
    Ingredients, Apples, Oranges, Oranges, Oranges, Oranges, Bananas
    

    增加快速值,直到与替换元素(橙子)不同

                                   slow                       fast
                                     V                          V
    Ingredients, Apples, Oranges, Oranges, Oranges, Oranges, Bananas
    

    快速将元素设置为缓慢的元素。

                                   slow                       fast
                                     V                          V
    Ingredients, Apples, Oranges, Bananas, Oranges, Oranges, Bananas
    

    增加两者。

                                            slow                  fast
                                              V                     V
    Ingredients, Apples, Oranges, Bananas, Oranges, Oranges, Bananas
    

    到了最后。

    将列表缩短为慢。

    Ingredients, Apples, Oranges, Bananas
    

答案 6 :(得分:0)

使用关联数组进行存在检查:

var exists = {}, i;
for (i = 0; i < arr.length; i += 1) {
    if (exists[arr[i]]) {
        arr.splice(i, 1);
        i--;
    } else {
        exists[arr[i]] = true;
    }
}
// arr should now have no dupes

答案 7 :(得分:0)

http://jsfiddle.net/XYsUm/

var ingredients = [
    "Apples",
    "Apples",
    "Oranges",
    "Oranges",
    "Oranges",
    "Bananas"
];

var uniqIngredients = {};

for (i in ingredients) {
    uniqIngredients[ingredients[i]] = true;
}

ingredients = [];

for (i in uniqIngredients) {
    ingredients.push(i);
}