Как объеденить массивы, если внутренние обьекты не идентичны?

Рейтинг: 0Ответов: 2Опубликовано: 11.02.2023

У меня есть два массива из объектов, я должен объединить эти массивы если внутренние объекты не совпадают. Но в массивах могут быть одинаковые объекты.

Как это можно сделать? Вот пример:

const firstArray = [
  {
    title: 'Повтряюший текст',
    price: 'Price'
  },
  {
    title: 'Title2',
    price: 'Price'
  }
]

const secondArray = [
  {
    title: 'Повтряюший текст',
    price: 'Price'
  },
  {
    title: 'Title3',
    price: 'Price'
  }
]

// В результат
const result = [
  {
    title: 'Повтряюший текст',
    price: 'Price'
  },
  {
    title: 'Title2',
    price: 'Price'
  },
  {
    title: 'Title3',
    price: 'Price'
  },
]

Ответы

▲ 0Принят

UPD: перечитал комментарии к вопросу, не обратил внимание что объекты имеют одинаковые поля. Решение оставлю как есть, может кому-то будет полезным

Возьмем входные данные из вопроса

const firstArray = [
  {
    title: 'Повтряюший текст',
    price: 'Price'
  },
  {
    title: 'Title2',
    price: 'Price'
  }
]

const secondArray = [
  {
    title: 'Повтряюший текст',
    price: 'Price'
  },
  {
    title: 'Title3',
    price: 'Price'
  }
]

Вся сложность в том, что нужно убрать дублирующиеся объекты. Но проверять нужно не их ссылки, а поля. Алгоритм следующий - необходимо проверять каждый новый объект, не находится ли уже объект с такими же полями в массиве:

const isEqual = (firstObj, secondObj) => {
  const firstObjKeys = Object.keys(firstObj);
  const secondObjKeys = Object.keys(secondObj);

  // Если объекты имеют разное кол-во ключей - они различны
  if (firstObjKeys.length !== secondObjKeys.length) return false;
  
  // Проходимся по всем ключам
  for (const key of firstObjKeys) {

    // Необходимо проверять на наличие ключа, в случае если значение окажется undefined
    const secondObjHasKey = key in secondObj;

    // Проверка самого значения
    const valueIsSame = firstObj[key] === secondObj[key];
    if (!secondObjHasKey || !valueIsSame) return false;
  }

  return true;
}

const array = [...firstArray, ...secondArray];
const result = [];

// Проходимся по объектам массива со всеми значениями
for (const obj of array) {
  // Проверяем каждый элемент на дубликат. Если хоть один дубликат найден - мы его не добавляем
  const isDuplicate = result.some(item => isEqual(obj, item));
  if (!isDuplicate) result.push(obj);
}

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

▲ 0

Применительно к тем массивам, что указал ТС, решение может выглядеть таким образом.

const first = [
  {
    title: 'Повтряюший текст',
    price: 'Price'
  },
  {
    title: 'Title2',
    price: 'Price'
  }
]

const second = [
  {
    title: 'Повтряюший текст',
    price: 'Price'
  },
  {
    title: 'Title3',
    price: 'Price'
  }
]
const result = []
let i = 0
let j = 0
while (first[i] || second[j]) {
  if (no(first[i])) result.push(first[i])
  if (no(second[j])) result.push(second[j])
  ++i
  ++j
}
console.log(result)

// проверка на наличие элемента в результате
function no(obj) {
  return !result.some(o => o.title === obj.title)
}