Как собрать 2 массива объектов и получить измененный объект массива

#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"  }  ]; }