Извлечение уникальных значений из массива объектов, где значение является вложенным объектом в JavaScript - PullRequest
1 голос
/ 19 марта 2020

Допустим, у меня есть следующий массив объектов в JavaScript:

const requests = [
  {
    id: 1,
    person: {
      id: 1
    }
  },
  {
    id: 2,
    person: {
      id: 1
    }
  },
  {
    id: 3,
    person: {
      id: 2
    }
  },
  {
    id: 4,
    person: {
      id: 3
    }
  },
  {
    id: 5,
    person: {
      id: 2
    }
  }
]

И то, что я написал ниже, будет go для каждого элемента в массиве, а затем создаст новый массив, содержащий только объект person.

const requestsPeopleIds = []
for (const request of requests) {
  requestsPeopleIds.push(request.person.id)
}

Затем я беру этот новый массив и создаю другой новый массив, используя Set, чтобы удалить дубликаты id s:

const uniquePeopleIds = Array.from(new Set(requestsPeopleIds))

Окончательный результат, как я и ожидал:

console.log(uniquePeopleIds) // [1, 2, 3]

, где это уникальные id людей, которые сделали запрос. Итак, из 5 запросов они были сделаны 3 людьми.

Должен быть более эффективный способ сделать это, поэтому я обращаюсь к вам stack overflow JS гуру .

Заранее спасибо.

Ответы [ 4 ]

3 голосов
/ 19 марта 2020

Я думаю, что вы получили основы. Вот способ ужесточить код:

var ids = new Set;
requests.forEach(i => ids.add(i.person.id));
1 голос
/ 19 марта 2020

Вы также можете сделать это с помощью метода map и синтаксиса распространения ....

const requests = [{"id":1,"person":{"id":1}},{"id":2,"person":{"id":1}},{"id":3,"person":{"id":2}},{"id":4,"person":{"id":3}},{"id":5,"person":{"id":2}}]
const result = [...new Set(requests.map(({ person: { id }}) => id))]
console.log(result)
0 голосов
/ 19 марта 2020

Я провел некоторое исследование и вывел некоторые интересные факты:

  1. Похоже, что когда у нас очень разные данные и массив больше, то коллекция Set показывает не лучшие результаты , Set очень оптимизированная коллекция, однако, на мой взгляд, она всегда должна проверять, был ли элемент уже добавлен в Set. И эта проверка займет O(n) сложность. Но мы можем использовать простые JavaScript object. Проверка, содержит ли object ключ, - O (1). Так что object будет иметь огромное преимущество перед Set.

  2. foreach Функция стрелки очень удобна, однако, простой for l oop быстрее.

  3. Добавление console.log делает Set самым быстрым решением, однако без console.log самым быстрым решением является комбинация for l oop и object.

Таким образом, наиболее код производительности без console.log() выглядит следующим образом:

const hashMap = {};
const uniques = [];
for (let index = 0; index < requests.length; index++) {  
  if (!hashMap.hasOwnProperty(requests[index].person.id)){
      hashMap[requests[index].person.id] = 1;
      uniques.push(requests[index].person.id);
  }
}

Однако наиболее производительный код с console.log() выглядит следующим образом (я не могу понять причину, по которой это происходит. Было бы здорово узнать, почему бывает):

var ids = new Set;
requests.forEach(i => ids.add(i.person.id));
console.log(ids)

Тесты:

0 голосов
/ 19 марта 2020

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

const requests = [{"id":1,"person":{"id":1}},{"id":2,"person":{"id":1}},{"id":3,"person":{"id":2}},{"id":4,"person":{"id":3}},{"id":5,"person":{"id":2}}]


// Take an empty object
const uniques = {};

// Iterate through the requests array and make person's id as a
// key of the object and put any value at this index (here I put 1).
requests.forEach(request => (uniques[request.person.id] = 1));

// Finally get the keys of the unique object.
console.log(Object.keys(uniques));
...