【问题标题】:Completely removing duplicate items from an array从数组中完全删除重复项
【发布时间】:2017-09-16 06:54:00
【问题描述】:

假设我有;

var array = [1,2,3,4,4,5,5];

我希望它成为;

var newArray = [1,2,3];

我想完全删除重复项,而不是将它们保留为唯一值。有没有办法通过reduce方法来实现?

【问题讨论】:

  • 为什么不使用过滤器?
  • 澄清一下,如果一个数字出现多次,您想删除该数字的所有实例 - 是否正确?所以你想要的输出是[1,2,3]?
  • 我不想得到重复的值。我想完全删除它们。
  • @Kinduser 大多数 OP 不知道他们不知道什么。你必须给他们怀疑的好处。 I'll just leave this here

标签: javascript arrays


【解决方案1】:

我猜它不会有什么出色的表现,但我喜欢这个主意。

var array = [1,2,3,4,4,5,5],
    res = array.reduce(function(s,a) {
      if (array.filter(v => v !== a).length == array.length-1) {
        s.push(a);
      }
      return s;
    }, []);
    console.log(res);

【讨论】:

    【解决方案2】:

    您可以将Array#filterArray#indexOfArray#lastIndexOf 一起使用,并且只返回共享相同索引的值。

    var array = [1, 2, 3, 4, 4, 5, 5],
        result = array.filter(function (v, _, a) {
            return a.indexOf(v) === a.lastIndexOf(v);
        });
    
    console.log(result);

    另一种方法是采用Map 并将值设置为false,如果之前已经看到过密钥。然后通过取地图的值来过滤数组。

    var array = [1, 2, 3, 4, 4, 5, 5],
        result = array.filter(
            Map.prototype.get,
            array.reduce((m, v) => m.set(v, !m.has(v)), new Map)
        );
    
    console.log(result);

    【讨论】:

    • 没想到lastIndexOf - 很好的解决方案!
    • 这很漂亮。我也没有想到 lastIndexOf。
    • 不错!第二个例子在算法顺序方面更好;它在过滤器中非常巧妙地使用了 thisArg,我只是通过阅读答案了解到的。谢谢!
    【解决方案3】:
    //Try with this code
    var arr = [1,2, 3,3,4,5,5,5,6,6];
    
    arr = arr.filter( function( item, index, inputArray ) {
               return inputArray.indexOf(item) == index;
          });
    

    还可以查看此链接https://fiddle.jshell.net/5hshjxvr/

    【讨论】:

      【解决方案4】:

      另一种选择是使用一个对象来跟踪一个元素被使用了多少次。这会破坏数组顺序,但在非常大的数组上应该更快。

      function nukeDuplications(arr) {
        const hash = {};
        arr.forEach(el => {
          const qty = hash[el] || 0;
          hash[el] = qty+1;
        });
        
        const ret = [];
        Object.keys(hash).forEach(key => {
          if (hash[key] === 1) {
            ret.push(Number(key));
          }
        })
        return ret;
      }
      
      var array = [1,2,3,4,4,5,5];
      console.log(nukeDuplications(array));

      【讨论】:

        【解决方案5】:

        一个稍微更有效的解决方案是循环数组 1 次并计算每个值中出现的次数并使用 .reduce() 将它们存储在一个对象中,然后使用 .filter() 再次循环数组以仅返回发生 1 次的项目。

        此方法还将保留数组的顺序,因为它仅使用对象键作为引用 - 它不会迭代它们。

        var array = [1,2,3,4,4,5,5];
        var valueCounts = array.reduce((result, item) => {
            if (!result[item]) {
                result[item] = 0;
            }
            result[item]++;
            return result;
        }, {});
         
        var unique = array.filter(function (elem) {
            return !valueCounts[elem] || valueCounts[elem] <= 1;
        }); 
         
        console.log(unique)

        【讨论】:

          【解决方案6】:

          另一个选择是使用一个对象来跟踪一个元素被使用了多少次。这会破坏数组顺序,但在非常大的数组上应该更快。

          // Both versions destroy array order.
          
          // ES6 version
          function nukeDuplications(arr) {
            "use strict";
            const hash = {};
            arr.forEach(el => {
              const qty = hash[el] || 0;
              hash[el] = qty + 1;
            });
          
            const ret = [];
            Object.keys(hash).forEach(key => {
              if (hash[key] === 1) {
                ret.push(Number(key));
              }
            })
            return ret;
          }
          
          // ES5 version
          function nukeDuplicationsEs5(arr) {
            "use strict";
            var hash = {};
            for (var i = 0; i < arr.length; i++) {
              var el = arr[i];
              var qty = hash[el] || 0;
              hash[el] = qty + 1;
            };
          
            var ret = [];
            for (let key in hash) {
              if (hash.hasOwnProperty(key)) {
                  if (hash[key] === 1) {
                    ret.push(Number(key));
                  }
                }
              }
              return ret;
            }
          
          
            var array = [1, 2, 3, 4, 4, 5, 5];
            console.log(nukeDuplications(array));
          
            console.log(nukeDuplicationsEs5(array));

          【讨论】:

            【解决方案7】:

            这里有很多过于复杂且运行缓慢的代码。这是我的解决方案:

            let numbers = [1,2,3,4,4,4,4,5,5]
            let filtered = []
            
            numbers.map((n) => {
                if(numbers.indexOf(n) === numbers.lastIndexOf(n)) // If only 1 instance of n
                    filtered.push(n)
            })
            
            console.log(filtered)
            

            【讨论】:

              【解决方案8】:

              你可以使用这个功能:

              function isUniqueInArray(array, value) {
                let counter = 0;
                for (let index = 0; index < array.length; index++) {
                  if (array[index] === value) {
                    counter++;
                  }
                }
                if (counter === 0) {
                  return null;
                }
                return counter === 1 ? true : false;
              }
              
              const array = [1,2,3,4,4,5,5];
              let uniqueValues = [];
              
              array.forEach(element => {
                if(isUniqueInArray(array ,element)){
                  uniqueValues.push(element);
                }
              });
              
              console.log(`the unique values is ${uniqueValues}`);

              如果对您有帮助,您可以从我的包 https://www.npmjs.com/package/jotils 或直接从位 https://bit.dev/joshk/jotils/is-unique-in-array 安装 isUniqueInArray 函数。

              【讨论】:

                【解决方案9】:

                我的答案是使用如下的地图和过滤器:

                x = [1,2,3,4,2,3]
                x.map(d => x.filter(i => i == d).length < 2 ? d : null).filter(d => d != null)
                // [1, 4]
                

                【讨论】:

                  【解决方案10】:

                  自 ES2017 起支持 Object.values(不用说 - 不在 IE 上)。 累加器是一个对象,每个键都是一个值,因此重复项会在它们覆盖相同的键时被删除。 但是,此解决方案可能存在行为不当的值(null、未定义等)的风险,但可能对现实生活场景有用。

                  let NukeDeps = (arr) => {
                    return Object.values(arr.reduce((curr, i) => {
                      curr[i] = i;
                      return curr;
                    }, {}))  
                  }
                  

                  【讨论】:

                    【解决方案11】:

                    我想用我再次阅读时想出的答案来回答我的问题

                    const array = [1, 2, 3, 4, 4, 5, 5];
                    const filtered = array.filter(item => {
                      const { length }  = array.filter(currentItem => currentItem === item)
                      if (length === 1) {
                         return true;
                       }
                    });
                    console.log(filtered)
                    

                    【讨论】:

                    • 一个班轮:array.filter(x =&gt; array.filter(y =&gt; x === y).length === 1)
                    猜你喜欢
                    • 2020-11-09
                    • 2016-01-04
                    • 2018-09-26
                    • 2014-03-10
                    • 1970-01-01
                    • 2021-06-01
                    • 2019-07-19
                    • 2011-06-29
                    相关资源
                    最近更新 更多