сравните два массива в javascript и удалите объект, который есть у обоих массивов

У меня есть 2 массива:

0: {id: 2, name: "TMA"}
1: {id: 3, name: "Hibbernate"}
0: {id: 1, name: "FB.DE"}
1: {id: 2, name: "TMA"}
2: {id: 3, name: "Hibbernate"}
3: {id: 4, name: "Event.it A"}
4: {id: 5, name: "Projket 2"}
5: {id: 6, name: "Projekt 1"}

Я хочу сравнить их и удалить объекты с идентификаторами 2 и 3, потому что они есть в обоих массивах, и в этом сходство.

Это мой код до сих пор:

const projectListOutput = projectsOfPersonArray.filter(project => data.includes(project));
        console.log(projectListOutput);

Но каждый раз, когда я запускаю этот проект,ListOutput пуст.


person Gerrit    schedule 05.06.2020    source источник
comment
оба массива отсортированы?   -  person Ehsan Nazeri    schedule 05.06.2020
comment
Когда вы имеете в виду залив, отсортированный с помощью функции sort(), тогда да.   -  person Gerrit    schedule 05.06.2020
comment
Какой массив projectsOfPersonArray, а какой data? Потому что если короткий projectsOfPersonArray, то вы отфильтровали оба элемента...   -  person Heretic Monkey    schedule 05.06.2020


Ответы (5)


При использовании includes не сравнивайте объекты, просто создайте data как массив строк. Остальной код аналогичен тому, что у вас есть.

arr1 = [
  { id: 2, name: "TMA" },
  { id: 3, name: "Hibbernate" },
];

arr2 = [
  { id: 1, name: "FB.DE" },
  { id: 2, name: "TMA" },
  { id: 3, name: "Hibbernate" },
  { id: 4, name: "Event.it A" },
  { id: 5, name: "Projket 2" },
  { id: 6, name: "Projekt 1" },
];

const data = arr1.map(({ id }) => id);
const result = arr2.filter(({ id }) => !data.includes(id));

console.log(result);

person Siva K V    schedule 06.06.2020

Ваш массив data, вероятно, не содержит точно такие же ссылки на объекты, как projectsOfPersonArray. Посмотрите на код ниже:

[{ foo: 'bar' }].includes({ foo: 'bar' });
// false

Объекты выглядят одинаковыми, но они не используют одну и ту же ссылку (= они не одинаковы). Безопаснее использовать includes с примитивными значениями, такими как числа или строки. Например, вы можете проверить идентификаторы ваших объектов вместо полных объектов.

person KorHosik    schedule 05.06.2020

Вы сравниваете разные объекты, поэтому каждый объект уникален.

Для фильтрации необходимо сравнить все свойства или использовать строку JSON, если порядок свойств одинаковый.

var exclude = [{ id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }],
    data = [{ id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }, { id: 1, name: "FB.DE" }, { id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }, { id: 4, name: "Event.it A" }, { id: 5, name: "Projket 2" }, { id: 6, name: "Projekt 1" }],
    result = data.filter(project =>
        !exclude.some(item => JSON.stringify(item) === JSON.stringify(project))
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

person Nina Scholz    schedule 05.06.2020

Вы можете сделать что-то похожее на следующее:

const source = [{
    id: 1,
    name: "FB.DE"
  },
  {
    id: 2,
    name: "TMA"
  },
  {
    id: 3,
    name: "Hibbernate"
  },
  {
    id: 4,
    name: "Event.it A"
  },
  {
    id: 5,
    name: "Projket 2"
  },
  {
    id: 6,
    name: "Projekt 1"
  }
]
const toRemove = [{
    id: 2,
    name: "TMA"
  },
  {
    id: 3,
    name: "Hibbernate"
  }
]

/**create object where keys is object "id" prop, and value is true**/
const toRemoveMap = toRemove.reduce((result, item) => ({
  ...result,
  [item.id]: true
}), {})

const result = source.filter(item => !toRemoveMap[item.id])

Вы можете сделать из него функцию:

function removeArrayDuplicates (sourceArray, duplicatesArray, accessor) {
  const toRemoveMap = duplicatesArray.reduce((result, item) => ({
    ...result,
    [item[accessor]]: true
  }), {});
  return sourceArray.filter(item => !toRemoveMap[item[accessor]])
}

removeArrayDuplicates(source, toRemove, 'id')

Или, что еще лучше, вы можете заставить его работать с функцией, а не просто с методом доступа к свойству:

function removeDuplicates (sourceArray, duplicatesArray, accessor) {
  let objectSerializer = obj => obj[accessor];
  if(typeof accessor === 'function') {
    objectSerializer = accessor;
  }
  const toRemoveMap = duplicatesArray.reduce((result, item) => ({
    ...result,
    [objectSerializer(item)]: true
  }), {});
  return sourceArray.filter(item => !toRemoveMap[objectSerializer(item)])
}

removeDuplicates(source, toRemove, (obj) => JSON.stringify(obj))
person Bohdan Kontsedal    schedule 05.06.2020

Эта функция поможет вам объединить два отсортированных массива

var arr1 = [
  { id: 2, name: 'TMA' },
  { id: 3, name: 'Hibbernate' },
]
var arr2 = [
  { id: 1, name: 'FB.DE' },
  { id: 2, name: 'TMA' },
  { id: 3, name: 'Hibbernate' },
  { id: 4, name: 'Event.it A' },
  { id: 5, name: 'Projket 2' },
]
function mergeArray(array1, array2) {
  var result = []
  var firstArrayLen = array1.length
  var secondArrayLen = array2.length
  var i = 0 // index for first array
  var j = 0 // index for second array
  while (i < firstArrayLen || j < secondArrayLen) {
    if (i === firstArrayLen) { // first array doesn't have any other members
      while (j < secondArrayLen) { // we copy rest members of first array as a result
        result.push(array2[j])
        j++
      }
    } else if (j === secondArrayLen) { // second array doesn't have any other members
      while (i < firstArrayLen) { // we copy the rest members of the first array to the result array
        result.push(array1[i])
        i++
      }
    } else if (array1[i].id < array2[j].id) {
      result.push(array1[i])
      i++
    } else if (array1[i].id > array2[j].id) {
      result.push(array2[j])
      j++
    } else {
      result.push(array1[i])
      i++
      j++
    }
  }
  return result
}

console.log(mergeArray(arr1,arr2));
person Ehsan Nazeri    schedule 05.06.2020