Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array

后端 未结 30 2970
再見小時候
再見小時候 2020-11-21 04:35

I need to check a JavaScript array to see if there are any duplicate values. What\'s the easiest way to do this? I just need to find what the duplicated values are - I don\'

30条回答
  •  有刺的猬
    2020-11-21 05:36

    UPDATED: The following uses an optimized combined strategy. It optimizes primitive lookups to benefit from hash O(1) lookup time (running unique on an array of primitives is O(n)). Object lookups are optimized by tagging objects with a unique id while iterating through so so identifying duplicate objects is also O(1) per item and O(n) for the whole list. The only exception is items that are frozen, but those are rare and a fallback is provided using an array and indexOf.

    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;
    }();
    

    If you have ES6 Collections available, then there is a much simpler and significantly faster version. (shim for IE9+ and other browsers here: 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;
        }
      });
    }
    

提交回复
热议问题