Lodash: Получить повторяющиеся значения из массива

Скажем, у меня есть такой массив: [1, 1, 2, 2, 3]

Я хочу получить дубликаты, которые в этом случае: [1, 2]

Поддерживает ли это lodash? Я хочу сделать это как можно короче.

Ответы

Ответ 1

Вы можете использовать это:

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

Обратите внимание, что если число появляется в вашем массиве более двух раз, вы всегда можете использовать _.uniq.

Ответ 2

Другой способ состоит в том, чтобы группировать по уникальным элементам и возвращать групповые ключи с более чем 1 элементом

_([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

Ну, вы можете использовать этот фрагмент кода, который намного быстрее, так как он имеет сложность 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]

Ответ 7

вот мой, es6-like, deps-free, ответ. с фильтром вместо редуктора

// 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 здесь :)

Ответ 8

Надеюсь, что решение ниже поможет вам, и оно будет полезно в любых условиях

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

Ответ 9

Вот еще одно краткое решение:

let data = [1, 1, 2, 2, 3]

let result = _.uniq(_.filter(data, (v, i, a) => a.indexOf(v) !== i))

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Ответ 10

Не нужно использовать lodash, вы можете использовать следующий код:

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

Ответ 11

Вы можете использовать counter объект. Это будет иметь каждое число в качестве ключа и общее количество вхождений в качестве их значения. Вы можете использовать filter чтобы получить числа, когда счетчик для номера становится 2

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

console.log(duplicates)