Сравнение двух массивов с объектами

Существует два массива:

const arr1 = [
  {id:1},
  {id:2},
  {id:3},
  {id:4}
]

const arr2 = [
  {id:1},
  {id:4},
  {id:5},
]

Мне необходимо сравнить два массива и создать третий из объектов, в которых id совпадает, т.е. arr3=[{id:1},{id:4}]

Я пользуюсь простым перебором обоих мссивов, но думаю, это долго:

arr1.forEach((item) => {
            arr2.forEach((item2) => {
                if (item.id == item2.id) {
                    arr3.push(item);
                }
            });
        });

Подскажите, пожалуйста, наиболее быстрое выполнение. Спасибо!


Ответы (2 шт):

Автор решения: PZBird

Тяжело представить вычисление пересечения массива без переобходов. Единственное, что могу предложить - сократить количество операций.

Для начала, стоит определить самый маленький массив, так как результирующий массив не будет больше самого маленького, но позволит сократить количество обходов для ряда значений, которые есть в большем, но отсутствуют в меньшем массиве. Это позволит убрать push и использовать filter.

Вторым этапом, нам нет нужды во втором массива обходить его весь, как у вас. Достаточно первого совпадения, в этом нам поможет some. Таким образом мы гарантированно обойдем оба массива только когда нет ни одного соответствия. В случае с совпадением, мы выйдем при первом же совпадении.

const arr1 = [
  { id: 1 },
  { id: 2 },
  { id: 3 },
  { id: 4 }
]

const arr2 = [
  { id: 1 },
  { id: 4 },
  { id: 5 },
]

const leastArr = arr1.length < arr2.length ? arr1 : arr2;
const biggestArr = arr1.length >= arr2.length ? arr1 : arr2;

const resultArray = leastArr.filter((item) => {
  return biggestArr.some((item2) => item2.id === item.id)
});

console.log(resultArray);

→ Ссылка
Автор решения: vsemozhebuty

Можно попробовать сократить переборы за счёт вспомогательной структуры, но нужно тестировать, будет ли выигрыш. Из одного массива можно создать Set наличных идентификаторов, тогда при проходе по второму массиву можно будет дишь проверять наличие идентирфикатора в Set, это быстрее, чем перебирать массив. В итогде на всё потребуется только по одному перебору на каждый массив, но будут расходы на создание Set и проверки в нём.

const arr1 = [
  {id:1},
  {id:2},
  {id:3},
  {id:4}
];

const arr2 = [
  {id:1},
  {id:4},
  {id:5},
];

const set = new Set();
for (const { id } of arr1) set.add(id);

const intersection = arr2.filter(({ id }) => set.has(id));
console.log(intersection);

→ Ссылка