#javascript #angular #typescript #ecmascript-6
Вопрос:
У меня есть 2 массива. Мне нужно показывать только данные, которые не совпадают со вторым массивом.
array1 = [
{
country: "usa",
child: [
{ id: 1, name: "fvsdfsd" },
{ id: 2, name: "hhghhhfhj" },
],
},
{
country: "CA",
child: [
{ id: 3, name: "adsada" },
{ id: 4, name: "hhghhhfhj" },
],
},
{
country: "AU",
child: [
{ id: 5, name: "seven" },
{ id: 6, name: "hhghhhfhj" },
],
},
];
array2 = [
{ id: 1, name: "fvsdfsd" },
{ id: 2, name: "hhghhhfhj" },
];
Результат:
[
{
country: "usa",
child: [],
},
{
country: "CA",
child: [
{ id: 3, name: "adsada" },
{ id: 4, name: "hhghhhfhj" },
],
},
{
country: "AU",
child: [
{ id:5, name: "seven" },
{ id:6, name: "hhghhhfhj" },
],
},
]
Я пытаюсь так, но это не работает
array1.filter(data => !array2.includes(data.child));
Комментарии:
1. К вашему сведению, ваши массивы не являются допустимыми массивами javascript.
Ответ №1:
Ваш код не работает из-за того, как Ecma/Javascript выполняет тестирование на равенство. Array.includes()
использует тот же алгоритм Valuezero для определения того, являются ли две вещи «равными».
[И равенство в Javascript является странным]
Сравнение объектов выполняется по ссылке, поэтому два объекта равны, если (и только если) они являются одним и тем же объектом в памяти. Например
const areEqual = {a:1,b:2} === {a:1,b:2}
есть false
, как есть
const areEqual = {a:1,b:2} == {a:1,b:2}
Вам нужно провести глубокую проверку на равенство с помощью чего-то вроде lodash isEqual()
:
const _ = require('lodash');
const areEqual = _.isEqual( {a:1,b:2} , {a:1,b:2} ) ; // returns true
Так что вы должны быть в состоянии сказать что-то вроде:
const _ = require('lodash');
const filtered = array1.map( o => {
return {
...o,
child: _.isEqual( o.child, array2 ) ? [] : o.child ),
}
});
Ответ №2:
Вы не можете сравнивать два разных объекта, используя includes в javascript, потому что includes использует ===. Только ссылки на один и тот же объект будут возвращать значение true с помощью ===. Вам нужно будет написать пользовательскую функцию, которая просматривает все ключи вашего объекта и сравнивает их значения между вашими двумя массивами.
В этой статье объясняются некоторые методы сравнения двух объектов: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/
Ответ №3:
Да, ты можешь попробовать вот так.
array1.map(item1 => ({ ...item1, child: item1.child.filter(childItem => !array2.find(item2 => JSON.stringify(item2) === JSON.stringify(childItem))) }));
Если ключи объекта расположены не в том порядке, как сказал Эверетт Гловьер, вы можете попробовать вот так.
array1.map(item1 => ({ ...item1, child: item1.child.filter(childItem => !array2.find(item2 => item2.id === childItem.id amp;amp; item2.name === childItem.name)) }));
Комментарии:
1. просто предупреждаю: ключи js не всегда находятся в одном и том же порядке, поэтому это может вернуть значение false.
2. Нет никакой гарантии, что два, казалось бы, идентичных (но разных) объекта javascript будут сериализованы в JSON со свойствами в одном и том же порядке. Из статьи MDN по
JSON.stringify()
теме : » Примечание: Свойства объектов, не являющихся массивами, не гарантируется, что они будут строиться в каком-либо определенном порядке. Не полагайтесь на упорядочение свойств внутри одного и того же объекта при построении».