Поиск уникальных объектов в массиве - PullRequest
6 голосов
/ 27 января 2020

У меня есть следующий массив:

const arr = [
            {company: 'a', date: '1'},
            {company: 'b', date: '1'},
            {company: 'c', date: '1'},
            {company: 'a', date: '2'},
            {company: 'a', date: '1'},
            {company: 'b', date: '2'},
          ]

Я просто хочу знать, как получить уникальные объекты внутри него. Я попытался использовать loda sh с этой командой:

uniqBy(arr, 'date');

Но он возвращает только:

[
  {company: "a", date: "1"},
  {company: "a", date: "2"}
]

Я хочу что-то вроде этого:

[
  {company: "a", date: "1"},
  {company: "a", date: "2"},
  {company: "b", date: "1"},
  {company: "b", date: "2"},
  {company: "c", date: "1"},
]

Есть ли способ в loda sh или vanilla JS сделать это?

Ответы [ 4 ]

7 голосов
/ 27 января 2020

С помощью reduce() в чистом виде js вы создали функцию, которая принимает массив объектов и массив ключей в качестве входных данных и возвращает массив, уникальный для всех этих ключей.

Вот шаги алгоритма:

  • Сначала нам нужно создать объект, используя reduce().
  • key этого объекта будут значениями необходимых ключей, которые предоставляются, каждый из которых соединен - (я упомянул keyString для каждого объекта в комментарии кода).
  • Объект, который будет иметь одинаковые keyString, означает, что одинаковые значения для данного массива keys будут автоматически появляться только один раз, потому что объект не может иметь дублирующиеся ключи
  • Наконец мы используем Object.values() чтобы создать массив.

const arr = [
            {company: 'a', date: '1'}, //keyString = "a-1"
            {company: 'b', date: '1'}, //keyString = "b-1"
            {company: 'c', date: '1'}, //keyString = "c-1"
            {company: 'a', date: '2'}, //keyString = "a-2"
            {company: 'a', date: '1'}, //keyString = "a-1"
            {company: 'b', date: '2'}, //keyString = "b-2"
            //The item at index 0 and index 4 have same keyString so only a single of them will remain in object.
          ] 

const uniqueBy = (arr, keys) => {
  const obj = arr.reduce((ac, a) => {
    let keyString = keys.map(k => a[k]).join('-');
    ac[keyString] = a;
    return ac;
  }, {});
  return Object.values(obj);
}

console.log(uniqueBy(arr, ['company', 'date']))
6 голосов
/ 27 января 2020

Эта комбинация функций loda sh должна сделать это:

_.uniqWith(arr, _.isEqual);

Если вы хотите рассмотреть только комбинацию свойств для уникальности и не учитывать другие свойства, вы используете uniqBy () с собственная функция, которая устанавливает критерий. Например:

const arr = [
            {company: 'a', date: '1', clients: 3},
            {company: 'b', date: '1', clients: 2},
            {company: 'c', date: '1', clients: 2},
            {company: 'a', date: '1', clients: 1}
          ]

const uniqArr = _.uniqBy(arr, function(obj){
  return obj.company + obj.date;
});

// => [
       {company: 'a', date: '1', clients: 3},
       {company: 'b', date: '1', clients: 2},
       {company: 'c', date: '1', clients: 2}
      ]

В этом примере свойство клиента не влияет на уникальность, поэтому последний объект будет исключен, поскольку свойства компании и даты совпадают с первым объектом.

2 голосов
/ 27 января 2020

Группируйте их, используя поля компании и даты, и используйте сокращение

const arr = [{
    company: 'a',
    date: '1'
  },
  {
    company: 'b',
    date: '1'
  },
  {
    company: 'c',
    date: '1'
  },
  {
    company: 'a',
    date: '2'
  },
  {
    company: 'a',
    date: '1'
  },
  {
    company: 'b',
    date: '2'
  },
];

const res = Object.values(arr.reduce((acc, curr) => {
  const key = ['company', 'date'].map(x => curr[x]).join('-');

  if (!acc[key]) {
    acc[key] = curr;
  }

  return acc;
}, {}));

console.log(res);
1 голос
/ 27 января 2020

Здесь с использованием метода reduce в одной строке.

const arr = [
  { company: "a", date: "1" },
  { company: "b", date: "1" },
  { company: "c", date: "1" },
  { company: "a", date: "2" },
  { company: "a", date: "1" },
  { company: "b", date: "2" }
];

const updated = Object.values(
  arr.reduce(
    (acc, curr) => ({
      ...acc,
      [`${curr.company}-${curr.date}`]: { ...curr }
    }),
    {}
  )
);

console.log(updated);
...