代码之家  ›  专栏  ›  技术社区  ›  Scott Saunders

获取数组中的所有非唯一值(即:重复/多次出现)

  •  354
  • Scott Saunders  · 技术社区  · 17 年前

    我需要检查一个JavaScript数组,看看是否有任何重复的值。最简单的方法是什么?我只需要找到被复制的值是什么-我实际上不需要它们的索引,也不需要它们被复制多少次。

    我知道我可以在数组中循环并检查所有其他值是否匹配,但似乎应该有一种更简单的方法。

    类似问题:

    71 回复  |  直到 6 年前
        1
  •  335
  •   Zameer Ansari    6 年前

    您可以对数组进行排序,然后遍历它,然后查看下一个(或上一个)索引是否与当前索引相同。假设您的排序算法是好的,这应该小于O(n) 2. ):

    const findDuplicates = (arr) => {
      let sorted_arr = arr.slice().sort(); // You can define the comparing function here. 
      // JS by default uses a crappy string compare.
      // (we use slice to clone the array so the
      // original array won't be modified)
      let results = [];
      for (let i = 0; i < sorted_arr.length - 1; i++) {
        if (sorted_arr[i + 1] == sorted_arr[i]) {
          results.push(sorted_arr[i]);
        }
      }
      return results;
    }
    
    let duplicatedArray = [9, 9, 111, 2, 3, 4, 4, 5, 7];
    console.log(`The duplicates in ${duplicatedArray} are ${findDuplicates(duplicatedArray)}`);

    参考: https://stackoverflow.com/a/57532964/8119511

        2
  •  211
  •   namgold Adam Comerford    5 年前

    function eliminateDuplicates(arr) {
      var i,
          len = arr.length,
          out = [],
          obj = {};
    
      for (i = 0; i < len; i++) {
        obj[arr[i]] = 0;
      }
      for (i in obj) {
        out.push(i);
      }
      return out;
    }
    
    console.log(eliminateDuplicates([1,6,7,3,6,8,1,3,4,5,1,7,2,6]))

    资料来源: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/

        3
  •  190
  •   Community Mohan Dere    5 年前

    这是我从复制线程(!)中得到的答案:

    查找重复项

    var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']
    
    var uniq = names
      .map((name) => {
        return {
          count: 1,
          name: name
        }
      })
      .reduce((a, b) => {
        a[b.name] = (a[b.name] || 0) + b.count
        return a
      }, {})
    
    var duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1)
    
    console.log(duplicates) // [ 'Nancy' ]

    @Dmytro Laptin指出了一些可以删除的代码。这是同一代码的更紧凑版本。使用一些ES6技巧和高阶函数:

    const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']
    
    const count = names =>
      names.reduce((a, b) => ({ ...a,
        [b]: (a[b] || 0) + 1
      }), {}) // don't forget to initialize the accumulator
    
    const duplicates = dict =>
      Object.keys(dict).filter((a) => dict[a] > 1)
    
    console.log(count(names)) // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
    console.log(duplicates(count(names))) // [ 'Nancy' ]
        4
  •  74
  •   flu    10 年前

    在数组中查找重复值

    这应该是在数组中实际查找重复值的最短方法之一。正如OP特别要求的那样, .

    var input = [1, 2, 3, 1, 3, 1];
    
    var duplicates = input.reduce(function(acc, el, i, arr) {
      if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
    }, []);
    
    document.write(duplicates); // = 1,3 (actual array == [1, 3])

    这不需要排序或任何第三方框架。它也不需要手动循环。它具有各种价值 indexOf() (或者更清楚地说,是 strict comparision operator )支持。

    因为 reduce() 和 它至少需要IE 9。

        5
  •  70
  •   Laurent Payot    7 年前

    短的 一个班轮来获取副本:

    [1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]
    

    要获得无重复项的阵列,只需反转条件:

    [1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]
    

    filter() 在我下面的旧答案中;)


    当您只需要按照中的要求检查是否存在重复项时 this question 你可以使用 every() 方法:

    [1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true
    
    [1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false
    

    every() 不适用于IE 8及以下版本。

        6
  •  29
  •   karim79    17 年前

    您可以添加此函数,或者调整它并将其添加到Javascript的数组原型中:

    Array.prototype.unique = function () {
        var r = new Array();
        o:for(var i = 0, n = this.length; i < n; i++)
        {
            for(var x = 0, y = r.length; x < y; x++)
            {
                if(r[x]==this[i])
                {
                    alert('this is a DUPE!');
                    continue o;
                }
            }
            r[r.length] = this[i];
        }
        return r;
    }
    
    var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
    var unique = arr.unique();
    alert(unique);
    
        7
  •  27
  •   user748221 user748221    14 年前

    更新:以下使用优化的组合策略。它优化了原语查找,以从哈希O(1)查找时间(运行)中获益 unique

    var unique = function(){
      var hasOwn = {}.hasOwnProperty,
          toString = {}.toString,
          uids = {};
    
      function uid(){
        var key = Math.random().toString(36).slice(2);
        return key in uids ? uid() : uids[key] = key;
      }
    
      function unique(array){
        var strings = {}, numbers = {}, others = {},
            tagged = [], failed = [],
            count = 0, i = array.length,
            item, type;
    
        var id = uid();
    
        while (i--) {
          item = array[i];
          type = typeof item;
          if (item == null || type !== 'object' && type !== 'function') {
            // primitive
            switch (type) {
              case 'string': strings[item] = true; break;
              case 'number': numbers[item] = true; break;
              default: others[item] = item; break;
            }
          } else {
            // object
            if (!hasOwn.call(item, id)) {
              try {
                item[id] = true;
                tagged[count++] = item;
              } catch (e){
                if (failed.indexOf(item) === -1)
                  failed[failed.length] = item;
              }
            }
          }
        }
    
        // remove the tags
        while (count--)
          delete tagged[count][id];
    
        tagged = tagged.concat(failed);
        count = tagged.length;
    
        // append primitives to results
        for (i in strings)
          if (hasOwn.call(strings, i))
            tagged[count++] = i;
    
        for (i in numbers)
          if (hasOwn.call(numbers, i))
            tagged[count++] = +i;
    
        for (i in others)
          if (hasOwn.call(others, i))
            tagged[count++] = others[i];
    
        return tagged;
      }
    
      return unique;
    }();
    

    如果您有可用的ES6集合,那么有一个更简单、速度更快的版本。(适用于IE9+和其他浏览器的垫片如下: https://github.com/Benvie/ES6-Harmony-Collections-Shim )

    function unique(array){
      var seen = new Set;
      return array.filter(function(item){
        if (!seen.has(item)) {
          seen.add(item);
          return true;
        }
      });
    }
    
        8
  •  22
  •   Angel David Calderaro Pacciott    11 年前
    var a = ["a","a","b","c","c"];
    
    a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})
    
        9
  •  22
  •   bluesmoon    10 年前

    这会让你得到你想要的,只是复制品。

    function find_duplicates(arr) {
      var len=arr.length,
          out=[],
          counts={};
    
      for (var i=0;i<len;i++) {
        var item = arr[i];
        counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
        if (counts[item] === 2) {
          out.push(item);
        }
      }
    
      return out;
    }
    
    find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.
    
        10
  •  19
  •   vsync    5 年前

    发现 非唯一 来自3个数组(或更多)的值:

    ES2015

    //          🚩🚩  🚩   🚩             🚩 
    var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
        arr2 = [1,2,511,12,50],
        arr3 = [22,0],
        merged,
        nonUnique;
    
    // Combine all the arrays to a single one
    merged = arr.concat(arr2, arr3)
    
    // create a new (dirty) Array with only the non-unique items
    nonUnique = merged.filter((item,i) => merged.includes(item, i+1))
    
    // Cleanup - remove duplicate & empty items items 
    nonUnique = [...new Set(nonUnique)]
    
    console.log(nonUnique)

    2015年前:

    unique 方法在 Array 原型 “声明性” 语法。我不建议在大型项目上使用这种方法,因为它很可能会与具有相同自定义名称的另一种方法发生冲突。

    Array.prototype.unique = function () {
        var arr = this.sort(), i=arr.length; // input must be sorted for this to work
        while(i--)
          arr[i] === arr[i-1] && arr.splice(i,1) // remove duplicate item
        return arr
    }
    
    Array.prototype.nonunique = function () {
        var arr = this.sort(), i=arr.length, res = []; // input must be sorted for this to work
        while(i--)
          arr[i] === arr[i-1] && (res.indexOf(arr[i]) == -1) && res.push(arr[i]) 
        return res
    }
    
    //          🚩🚩  🚩    🚩            🚩 
    var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
        arr2 = [1,2,511,12,50],
        arr3 = [22,0],
        // merge all arrays & call custom Array Prototype - "unique"
        unique = arr.concat(arr2, arr3).unique(),
        nonunique = arr.concat(arr2, arr3).nonunique()
    
    console.log(unique)     // [1,12,2,22,3,4,5,50,511,6,7,8]
    console.log(nonunique)  // [1,12,2,22,3,4,5,50,511,6,7,8]
        11
  •  14
  •   Marco Allori    14 年前

    function hasDuplicate(arr){
        return (arr.length != _.uniq(arr).length);
    }
    
        12
  •  8
  •   Oleg Abrazhaev    8 年前

    这是我的简单的单线解决方案。

    它首先搜索非唯一元素,然后使用Set使找到的数组唯一。

    因此,我们最终得到了一个重复数组。

    var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];
    
    console.log([...new Set(
      array.filter((value, index, self) => self.indexOf(value) !== index))]
    );
        13
  •  8
  •   lukaszkups    7 年前

    这是我的建议(ES6):

    let a = [1, 2, 3, 4, 2, 2, 4, 1, 5, 6]
    let b = [...new Set(a.sort().filter((o, i) => o !== undefined && a[i + 1] !== undefined && o === a[i + 1]))]
    
    // b is now [1, 2, 4]
    
        14
  •  7
  •   sravan ganji    6 年前

    一行简单方式

    var arr = [9,1,2,4,3,4,9]
    console.log(arr.filter((ele,indx)=>indx!==arr.indexOf(ele))) //get the duplicates
    console.log(arr.filter((ele,indx)=>indx===arr.indexOf(ele))) //remove the duplicates
        15
  •  7
  •   nircraft    5 年前

    以下是我能想到的最简单的解决方案:

    const arr = [-1, 2, 2, 2, 0, 0, 0, 500, -1, 'a', 'a', 'a']
    
    const filtered = arr.filter((el, index) => arr.indexOf(el) !== index)
    // => filtered = [ 2, 2, 0, 0, -1, 'a', 'a' ]
    
    const duplicates = [...new Set(filtered)]
    
    console.log(duplicates)
    // => [ 2, 0, -1, 'a' ]

    就这样。

    注:

    1. 它适用于任何数字,包括 0 、字符串和负数,例如。 -1 - 相关问题: Get all unique values in a JavaScript array (remove duplicates)

    2. 原始数组 arr 保存( filter 返回新数组,而不是修改原始数组)

    3. filtered 数组包含 副本;信息技术 可以 还包含多个相同的值(例如,此处的筛选数组为 [ 2, 2, 0, 0, -1, 'a', 'a' ] )

    4. 如果你想得到 只有 可以使用的重复值(您不希望有多个具有相同值的重复值) [...new Set(filtered)] (ES6有一个对象 它只能存储唯一的值)

    希望这有帮助。

        16
  •  6
  •   mflodin    14 年前
    var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort();
    a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});
    

    或者当添加到数组的prototyp.chain时

    //copy and paste: without error handling
    Array.prototype.unique = 
       function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});}
    

    请看这里: https://gist.github.com/1305056

        17
  •  6
  •   Sivakumar Tadisetti zeah    8 年前

    它以O(n)(数组上的1次迭代)运行,并且不会重复出现超过2次的值

    const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd']
    const {
      dup
    } = arr.reduce(
      (acc, curr) => {
        acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1
        if (acc.items[curr] === 2) acc.dup.push(curr)
        return acc
      }, {
        items: {},
        dup: []
      },
    )
    
    console.log(dup)
    // ['hi', 'bye']
        18
  •  6
  •   chickens    6 年前

    最短香草JS :

    [1,1,2,2,2,3].filter((v,i,a) => a.indexOf(v) !== i) // [1, 2, 2]
    
        19
  •  5
  •   Souvanik Saha    5 年前

    可以使用filter方法和indexOf()获取所有重复值

    function duplicate(arr) {
        return duplicateArray = arr.filter((item, index) => arr.indexOf(item) !== index) 
    }
    

    arr.indexOf(项目) 将始终返回给定元素可以使用的第一个索引 建立

        20
  •  5
  •   attacomsian    5 年前

    最简单、最快捷的方法是使用 Set 对象:

    const numbers = [1, 2, 3, 2, 4, 5, 5, 6];
    
    const set = new Set(numbers);
    
    const duplicates = numbers.filter(item => {
        if (set.has(item)) {
            set.delete(item);
        } else {
            return item;
        }
    });
    
    console.log(duplicates);
    // [ 2, 5 ]
    
        21
  •  4
  •   Brandon Ferrara    13 年前

    这里有一个非常简单的方法:

    var codes = dc_1.split(',');
    var i = codes.length;
    while (i--) {
      if (codes.indexOf(codes[i]) != i) {
        codes.splice(i,1);
      }
    }
    
        22
  •  4
  •   Franc    9 年前

    使用ES6(或使用Babel或Typescipt),您只需执行以下操作:

    var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);
    

    https://es6console.com/j58euhbt/

        23
  •  4
  •   guest    9 年前

    使用ES6语法的简单代码(返回重复项的排序数组):

    let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};
    

    duplicates([1,2,3,10,10,2,3,3,10]);
    
        24
  •  4
  •   Muthu Kumaran    8 年前

    我刚刚想出了一个使用数组过滤器实现这一点的简单方法

        var list = [9, 9, 111, 2, 3, 4, 4, 5, 7];
        
        // Filter 1: to find all duplicates elements
        var duplicates = list.filter(function(value,index,self) {
           return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index;
        });
        
        console.log(duplicates);
        25
  •  4
  •   Divyanshu Rawat    6 年前

    这个答案可能也很有用,因为它利用了js reduce 操作员/方法 复制品 从数组中。

    const result = [1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], []);
    
    console.log(result);
        26
  •  4
  •   Richie Bendall    6 年前

    排名较高的答案有一些固有的问题,包括使用遗留javascript、顺序不正确或仅支持2个重复项。

    以下是解决这些问题的现代解决方案:

    const arrayNonUniq = array => {
        if (!Array.isArray(array)) {
            throw new TypeError("An array must be provided!")
        }
    
        return array.filter((value, index) => array.indexOf(value) === index && array.lastIndexOf(value) !== index)
    }
    
    arrayNonUniq([1, 1, 2, 3, 3])
    //=> [1, 3]
    
    arrayNonUniq(["foo", "foo", "bar", "foo"])
    //=> ['foo']
    

    您还可以使用npm包 array-non-uniq .

        27
  •  3
  •   Nosredna    17 年前

    下面的函数(前面提到的EliminatedReplicates函数的变体)似乎起到了作用,为输入返回test2,1,7,5[“test”、“test2”、“test2”、1,1,1,2,3,4,5,6,7,7,10,22,43,1,5,8]

    注意,这个问题在JavaScript中比在大多数其他语言中更为奇怪,因为JavaScript数组可以容纳任何内容。请注意,使用排序的解决方案可能需要提供适当的排序功能——我还没有尝试过这种方法。

    这个特定的实现至少适用于字符串和数字。

    function findDuplicates(arr) {
        var i,
            len=arr.length,
            out=[],
            obj={};
    
        for (i=0;i<len;i++) {
            if (obj[arr[i]] != null) {
                if (!obj[arr[i]]) {
                    out.push(arr[i]);
                    obj[arr[i]] = 1;
                }
            } else {
                obj[arr[i]] = 0;            
            }
        }
        return out;
    }
    
        28
  •  3
  •   gotofritz    14 年前

    仅限ES5(即IE8及以下版本需要过滤器()polyfill):

    var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ];
    
    arrayToFilter.
        sort().
        filter( function(me,i,arr){
           return (i===0) || ( me !== arr[i-1] );
        });
    
        29
  •  3
  •   vasa    10 年前

    var arr = [2, 1, 2, 2, 4, 4, 2, 5];
    
    function returnDuplicates(arr) {
      return arr.reduce(function(dupes, val, i) {
        if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) {
          dupes.push(val);
        }
        return dupes;
      }, []);
    }
    
    alert(returnDuplicates(arr));

    此函数 避免排序步骤 并使用reduce()方法将副本推送到新数组中(如果该数组中不存在)。

        30
  •  3
  •   Community Mohan Dere    9 年前

    这可能是从阵列中永久删除重复项的最快方法之一 比这里的大多数功能快10倍;在safari中速度提高78倍

    function toUnique(a,b,c){//array,placeholder,placeholder
     b=a.length;
     while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
    }
    var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
    toUnique(array);
    console.log(array);
    
    1. http://jsperf.com/wgu
    2. 演示: http://jsfiddle.net/46S7g/
    3. 更多: https://stackoverflow.com/a/25082874/2450730

    如果你看不懂上面的代码,可以去读一本javascript书,或者这里有一些关于较短代码的解释。 https://stackoverflow.com/a/21353032/2450730

    正如注释中所述,此函数确实返回一个带有uniques的数组,但问题是要查找重复的数组。在这种情况下,对该函数的简单修改允许将重复项推入数组,然后使用前面的函数 toUnique 删除重复项的重复项。

    function theDuplicates(a,b,c,d){//array,placeholder,placeholder
     b=a.length,d=[];
     while(c=--b)while(c--)a[b]!==a[c]||d.push(a.splice(c,1))
    }
    var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
    
    toUnique(theDuplicates(array));