#arrays #arrayobject
#массивы #arrayobject
Вопрос:
У меня есть 2 массива объектов. Один из них-старый массив, а другой-новый. То, что я хочу в качестве вывода, — это массив всех элементов, у которых какие-либо свойства изменились при сравнении старого и нового массивов. Он должен работать для любого свойства, которым может обладать объект, не ограничиваясь заданными 3. Однако вам не нужно обрабатывать вложенные объекты.
let old = [ { id: "f4101804-a587-4420-97d3-5691a93c9143", name: "Mice", price: "25" }, { id: "132a5f3b-7350-44e6-8ac8-3ba1b558ff1c", name: "acooer", price: "25" }, { id: "b1cf9e9d-e712-4624-b754-fb9c48a75716", name: "Yhgg", price: "25" }, { id: "01381e2c-ee25-4461-93cb-d54c812551e9", name: "anix", price: "25" } ]; let new = [ { id: "f4101804-a587-4420-97d3-5691a93c9143", name: "Mice", price: "25" }, { id: "132a5f3b-7350-44e6-8ac8-3ba1b558ff1c", name: "acoo", price: "25" }, { id: "b1cf9e9d-e712-4624-b754-fb9c48a75716", name: "Yhgg", price: "26" }, { id: "01381e2c-ee25-4461-93cb-d54c812551e9", name: "anix", price: "25" } ];
В данном примере изменилось свойство name второго элемента и свойство price 3-го элемента. Таким образом, результат должен быть
[ { id: '132a5f3b-7350-44e6-8ac8-3ba1b558ff1c', name: 'acoo', price: '25' }, { id: 'b1cf9e9d-e712-4624-b754-fb9c48a75716', name: 'Yhgg', price: '26' } ]
я пробовал это, но когда я меняю положение объекта, оно рассматривается как изменение объекта.
import "./styles.css"; const a = [ { id: "f4101804-a587-4420-97d3-5691a93c9143", name: "Mice", price: "25" }, { id: "132a5f3b-7350-44e6-8ac8-3ba1b558ff1c", name: "acooer", price: "25" }, { id: "b1cf9e9d-e712-4624-b754-fb9c48a75716", name: "Yhgg", price: "25" }, { id: "01381e2c-ee25-4461-93cb-d54c812551e9", name: "anix", price: "25" } ]; const b = [ { id: "f4101804-a587-4420-97d3-5691a93c9143", name: "Mice", price: "25" }, { id: "132a5f3b-7350-44e6-8ac8-3ba1b558ff1c", name: "acoo", price: "25" }, { id: "b1cf9e9d-e712-4624-b754-fb9c48a75716", name: "Yhgg", price: "26" }, { id: "01381e2c-ee25-4461-93cb-d54c812551e9", name: "anixx", price: "25" } ]; let result = b.filter( (elm) =gt; !a.map((elm) =gt; JSON.stringify(elm)).includes(JSON.stringify(elm)) ); console.log(result); document.getElementById("app").innerHTML = JSON.stringify(result, null, 2);
Комментарии:
1. На SO принято просить помощи в написании кода, который вы написали, а не просить помощи в написании кода. Пожалуйста, отредактируйте вопрос, чтобы показать попытку решения.
2. я кодировал почти все. но когда я меняю положение объекта, это рассматривается как изменение объекта. решение есть в ссылке см.
Ответ №1:
Предикат фильтра операции содержит несколько ошибок, в том числе использование одного и того же фиктивного параметра elm
(скрытие параметра фильтра) и тестирование a map
, которое возвращает массив вместо a find
.
Вот улучшенный предикат:
let result = b.filter(bElement =gt; { return !a.find(aElement =gt; isEquivalent(aElement, bElement)) });
Обратите внимание на несколько вещей:
- фиктивные параметры называются в соответствии с массивом, из которого они получены
- return
!a.find
возвращает значение false для найденной вещи, в противном случае значение true - эквивалентность учитывается, поэтому ее можно рассматривать как собственную проблему
OP пытается использовать общий тест на эквивалентность, сравнивая строковые представления, независимо от того , есть ли JSON.stringify(someObjectA) === JSON.stringify(someObjectB)
, но у этого подхода есть недостатки.
Во-первых, обе строки должны быть построены до того, как произойдет какое-либо сравнение. Что делать, если объекты огромны, но различаются в каждом ключе? Это можно было бы проверить перед созданием (а затем отбрасыванием) двух огромных строк.
Еще один недостаток связан с возможностью различных реализаций JS для создания разного порядка ключей stringify
. В то время как большинство реализаций создают одну и ту же строку, порядок ключей не гарантируется языком (насколько я знаю).
Приведенный ниже фрагмент содержит две альтернативы эквивалентности: isEquivalent_0()
использует опрометчивый тест stringify. isEquivalent_1()
выполняет неглубокую проверку ценностей. Он отключается, как только находит несоответствие ключа или значения, и не создает промежуточных (мусорных) объектов.
const a = aData(); const b = bData(); // this equivalence compares string representation of objects function isEquivalent_0(objA, objB) { return JSON.stringify(objA) === JSON.stringify(objB) } // this shallow equivalence checks keys and values, and terminates // as soon as a mismatch is found function isEquivalent_1(objA, objB) { for (aKey in objA) { if (!(aKey in objB)) return false; if (objA[aKey] !== objB[aKey]) return false; } for (bKey in objB) { if (!(bKey in objA)) return false; if (objA[aKey] !== objB[aKey]) return false; } return true; } let result = b.filter(bElement =gt; { return !a.find(aElement =gt; isEquivalent_1(aElement, bElement)) }); console.log(result); function aData() { return [{ id: "f4101804-a587-4420-97d3-5691a93c9143", name: "Mice", price: "25" }, { id: "132a5f3b-7350-44e6-8ac8-3ba1b558ff1c", name: "acooer", price: "25" }, { id: "b1cf9e9d-e712-4624-b754-fb9c48a75716", name: "Yhgg", price: "25" }, { id: "01381e2c-ee25-4461-93cb-d54c812551e9", name: "anix", price: "25" } ]; } function bData() { return [{ id: "f4101804-a587-4420-97d3-5691a93c9143", name: "Mice", price: "25" }, { id: "132a5f3b-7350-44e6-8ac8-3ba1b558ff1c", name: "acoo", price: "25" }, { id: "b1cf9e9d-e712-4624-b754-fb9c48a75716", name: "Yhgg", price: "26" }, { id: "01381e2c-ee25-4461-93cb-d54c812551e9", name: "anix", price: "25" } ]; }