【问题标题】:lodash: Get duplicate values from an arraylodash:从数组中获取重复值
【发布时间】:2015-10-19 07:54:01
【问题描述】:

假设我有一个这样的数组:[1, 1, 2, 2, 3]

我想得到这种情况下的重复项:[1, 2]

lodash 支持这个吗?我想以尽可能短的方式完成。

【问题讨论】:

标签: javascript arrays lodash


【解决方案1】:

你可以用这个:

_.filter(arr, (val, i, iteratee) => _.includes(iteratee, val, i + 1));

请注意,如果一个数字在您的数组中出现两次以上,您始终可以使用_.uniq

【讨论】:

  • 单线,带有一些 ES2015 糖:const duplicates = _.filter(array, (value, index, iteratee) => _.includes(iteratee, value, index + 1))
  • 如果您使用_.find 而不是_.includes _.filter(array, (value, index, iteratee) => { return _.find(iteratee, value, index + 1) }),它适用于对象和更复杂的结构。
  • 您能否为不熟悉 iteratee 的人添加一个解释?
  • @ahong iteratee===array 这相当于一个嵌套循环for(;;){ for(;;){
  • @Vitim.us 我理解嵌套循环,但iteratee===array 是什么意思?
【解决方案2】:

另一种方法是按唯一项目分组,并返回具有多个项目的组键

_([1, 1, 2, 2, 3]).groupBy().pickBy(x => x.length > 1).keys().value()

【讨论】:

    【解决方案3】:
    var array = [1, 1, 2, 2, 3];
    var groupped = _.groupBy(array, function (n) {return n});
    var result = _.uniq(_.flatten(_.filter(groupped, function (n) {return n.length > 1})));
    

    这也适用于未排序的数组。

    【讨论】:

    • 对于较大的数组,这似乎比公认的答案要快得多。干得好。
    【解决方案4】:

    另一种方式,但使用过滤器和 ecmaScript 2015 (ES6)

    var array = [1, 1, 2, 2, 3];
    
    _.filter(array, v => 
      _.filter(array, v1 => v1 === v).length > 1);
    
    //→ [1, 1, 2, 2]
    

    【讨论】:

    • 我喜欢,很简单!诀窍在于它识别子过滤器上是否存在多个。
    【解决方案5】:

    使用countBy() 后跟reduce() 怎么样?

    const items = [1,1,2,3,3,3,4,5,6,7,7];
    
    const dup = _(items)
        .countBy()
        .reduce((acc, val, key) => val > 1 ? acc.concat(key) : acc, [])
        .map(_.toNumber)
    
    console.log(dup);
    // [1, 3, 7]
    

    http://jsbin.com/panama/edit?js,console

    【讨论】:

      【解决方案6】:

      纯JS解决方案:

      export function hasDuplicates(array) {
        return new Set(array).size !== array.length
      }
      

      对于对象数组:

      /**
       * Detects whether an array has duplicated objects.
       * 
       * @param array
       * @param key
       */
      export const hasDuplicatedObjects = <T>(array: T[], key: keyof T): boolean => {
        const _array = array.map((element: T) => element[key]);
      
        return new Set(_array).size !== _array.length;
      };
      

      【讨论】:

        【解决方案7】:

        这是另一个简洁的解决方案:

        let data = [1, 1, 2, 2, 3]
        
        let result = _.uniq(_.filter(data, (v, i, a) => a.indexOf(v) !== i))
        
        console.log(result)
        &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"&gt;&lt;/script&gt;

        _.uniq 负责处理 _.filter 回来的配音。

        与 ES6 和 Set 相同:

        let data = [1, 1, 2, 2, 3]
        
        let result = new Set(data.filter((v, i, a) => a.indexOf(v) !== i))
        
        console.log(Array.from(result))

        【讨论】:

          【解决方案8】:

          好吧,你可以使用这段代码,因为它的复杂度为 O(n),而且它不使用 Lodash,所以速度要快得多。

          [1, 1, 2, 2, 3]
          .reduce((agg,col) => {
            agg.filter[col] = agg.filter[col]? agg.dup.push(col): 2;
            return agg
           },
           {filter:{},dup:[]})
          .dup;
          
          //result:[1,2]
          

          【讨论】:

            【解决方案9】:

            这是我的,类似 es6,无依赖,答案。用过滤器代替减速器

            // this checks if elements of one list contains elements of second list 
            // example code
            [0,1,2,3,8,9].filter(item => [3,4,5,6,7].indexOf(item) > -1)
            
            // function
            const contains = (listA, listB) => listA.filter(item => listB.indexOf(item) > -1) 
            contains([0,1,2,3], [1,2,3,4]) // => [1, 2, 3]
            
            // only for bool
            const hasDuplicates = (listA, listB) => !!contains(listA, listB).length
            

            编辑: 嗯,我的坏处是:我已将 q 视为一般问题,但这仅适用于 lodash,但我的意思是 - 你不需要 lodash :)

            【讨论】:

              【解决方案10】:

              您可以使用counter 对象。这会将每个数字作为键,将出现的总数作为它们的值。当数字的计数器变为2时,您可以使用filter获取数字

              const array = [1, 1, 2, 2, 3],
                    counter = {};
                    
              const duplicates = array.filter(n => (counter[n] = counter[n] + 1 || 1) === 2)
              
              console.log(duplicates)

              【讨论】:

                【解决方案11】:

                希望以下解决方案对您有所帮助,并且在所有情况下都会有用

                  hasDataExist(listObj, key, value): boolean {
                    return _.find(listObj, function(o) { return _.get(o, key) == value }) != undefined;
                  }
                
                
                
                  let duplcateIndex = this.service.hasDataExist(this.list, 'xyz', value);
                

                【讨论】:

                  【解决方案12】:

                  不用lodash,可以使用如下代码:

                  function getDuplicates(array, key) {
                    return array.filter(e1=>{
                      if(array.filter(e2=>{
                        return e1[key] === e2[key];
                      }).length > 1) {
                        return e1;
                      }
                    })
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    为什么不只使用这个?

                    _.uniq([4, 1, 5, 1, 2, 4, 2, 3, 4]) // [4, 1, 5, 2, 3]
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2015-04-05
                      • 1970-01-01
                      • 2021-03-10
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2018-05-25
                      相关资源
                      最近更新 更多