Как правильно распределить 2 массива, перезаписывая старые значения, соответствующие идентификатору объекта - PullRequest
0 голосов
/ 17 июня 2020

Моя цель - объединить значения в обоих массивах, перезаписав объекты, соответствующие всем _id. Возможно ли это?

oldState = [
               { _id: 1, label: 'a' },
               { _id: 2, label: 'b' }, 
               { _id: 3, label: 'c' }
           ]

newState = [
               { _id: 2, label: 'updated b' },
               { _id: 3, label: 'updated c' }
           ]

Expected Result:
           [
               { _id: 1, label: 'a' },
               { _id: 2, label: 'updated b' }, 
               { _id: 3, label: 'updated c' }
           ]

Выполнение этого:

[...oldState, ...newState]

Результат:

[
    { _id: 1, label: 'a' },
    { _id: 2, label: 'b' }, 
    { _id: 3, label: 'c' },
    { _id: 2, label: 'updated b' }, 
    { _id: 3, label: 'updated c' }
]

Ответы [ 6 ]

2 голосов
/ 17 июня 2020

Я бы использовал Array.reduce() с картой в качестве аккумулятора. Код немного чище, и карта также сохраняет исходный порядок элементов (объект упорядочит их по числовому c значению _id):

const oldState = [{"_id":1,"label":"a"},{"_id":2,"label":"b"},{"_id":3,"label":"c"}]
const newState = [{"_id":2,"label":"updated b"},{"_id":3,"label":"updated c"}]
           
const result = Array.from(
  [...oldState, ...newState]
    .reduce((acc, item) => acc.set(item._id, item), new Map())
    .values()
)

console.log(result);
2 голосов
/ 17 июня 2020

Вы должны отметить, что синтаксис распространения не может сам по себе переопределять объекты с помощью указанного ключа c, вам нужно сделать это самостоятельно.

Вы можете использовать Array.prototype.reduce и сгруппировать объект на основе _id и перезаписывать объекты с тем же идентификатором.

var oldState = [
               { _id: 1, label: 'a' },
               { _id: 2, label: 'b' }, 
               { _id: 3, label: 'c' }
           ]

var newState = [
               { _id: 2, label: 'updated b' },
               { _id: 3, label: 'updated c' }
           ]
           
const res = oldState.concat(newState).reduce((acc, item) => {
   acc[item._id] = {...(acc[item._id] || {}), ...item};
   return acc;
}, {})

const sol = Object.values(res);
console.log(sol);
1 голос
/ 17 июня 2020

Я бы уменьшил все элементы до объекта, а затем получил бы значения объекта:

const oldState = [
  { _id: 1, label: 'a' },
  { _id: 2, label: 'b' }, 
  { _id: 3, label: 'c' }
];

const newState = [
  { _id: 2, label: 'updated b' },
  { _id: 3, label: 'updated c' }
];

const merge = (oldState, newState) => Object.values(
  [...oldState, ...newState].reduce((a, v) => (a[v._id] = v, a), {})
);

console.log(merge(oldState, newState));
1 голос
/ 17 июня 2020

Вы можете создать Map из вашего newState с ключами, являющимися идентификаторами объектов, а значениями - самими объектами. Затем вы можете сопоставить свой oldState и заменить любые старые объекты новыми объектами из карты, если ее идентификатор существует:

const oldState = [{ _id: 1, label: 'a' }, { _id: 2, label: 'b' }, { _id: 3, label: 'c' } ];
const newState = [{ _id: 2, label: 'updated b' }, { _id: 3, label: 'updated c' } ];

const newStateMap = new Map(newState.map(o => [o._id, o]));
const res = oldState.map(o => newStateMap.get(o._id) || o);
console.log(res);
0 голосов
/ 17 июня 2020

Можно создать объект, который будет содержать уникальные элементы, а затем использовать метод map для создания объединенного объекта:

const oldState = [
  { _id: 1, label: 'a' },
  { _id: 2, label: 'b' },
  { _id: 3, label: 'c' }
];

const newState = [
  { _id: 2, label: 'updated b' },
  { _id: 3, label: 'updated c' }
];

const mapping = new Map(newState.map(s => [s._id, s]))
const result = oldState.map((s, i)=> ({ ...mapping.get(s._id) || s}));
console.log(result);
0 голосов
/ 17 июня 2020

Вы можете создавать объекты и вставлять их в новый объект и извлекать из него значения.

const
    getObject = (array, key) => Object.fromEntries(array.map(o => [o[key], o])),
    oldState = [{ _id: 1, label: 'a' }, { _id: 2, label: 'b' }, { _id: 3, label: 'c' }],
    newState = [{ _id: 2, label: 'updated b' }, { _id: 3, label: 'updated c' }],
    result = Object.values({
        ...getObject(oldState, '_id'),
        ...getObject(newState, '_id')
    });

console.log(result);
...