Мне нужно установить объекты/массивы...
var test = [{id: 1, prop: 'bill', location: 'san diego'},{id: 11, prop: 'bright'}];
var test2 = [{id: 1, prop: 'casey'},{id: 11, prop: 'candle'}];
В конечном итоге я хочу, чтобы объекты из test2 изменили свойства в тесте, но сохранили свойство местоположения в исходном объекте, потому что оно не изменилось и даже не упоминалось в test2.
Что я сделал, так это настроил сопоставление этого ключа с идентификатором и использовал каждый объект в качестве значения.
Проблема возникает из-за того, что значение нового объекта по ключу полностью перезапишет предыдущий исходный объект. Поэтому свойство местоположения стирается из исходного массива.
в частности, из Object.assign() голый объект, не представленный в виде массива объектов, сохранит целостность исходного объекта и изменит только базовые свойства.
Вот пример того и другого:
массив объектов:
var o1 = [{id: 1, prop: 'bill', location: 'san diego'},{id: 11, prop: 'bright'}];
var o2 = [{id: 1, prop: 'casey'},{id: 11, prop: 'candle'}];
var o3 = { c: 3 };
var obj = Object.assign({}, o1, o2, o3);
console.info(obj); // 0: {id: 1, prop: "casey"} 1: {id: 11, prop: "candle"} c: 3
единственный объект:
var o1 = {id: 1, prop: 'bill', location: 'san diego'};
var o2 = {id: 1, prop: 'casey'};
var o3 = { c: 3 };
var obj = Object.assign({}, o1, o2, o3);
console.info(obj); // {id: 1, prop: "casey", location: "san diego", c: 3}
обработка объекта в одном формате имеет желаемый эффект, поэтому, возможно, ответ заключается в этом факте. Есть ли краткий способ сделать это или это должно быть построено в циклическом режиме, обрабатывающем одну запись за раз? Если да, то что может быть примером этого?
Вот код отображения, над которым я работал:
var test = [{id: 1, prop: 'bill', location: 'san diego'},{id: 11, prop: 'bright'}];
var first = new Map();
for (const value of test) {
//console.info(key + ' = ' + value.id);
first.set(value.id, value);
//console.info(first);
}
var test2 = [{id: 1, prop: 'casey'},{id: 11, prop: 'candle'}];
var second = new Map();
for (const value of test2) {
second.set(value.id, value);
}
var merged = new Map([...first, ...second]);
let mergedArray = [];
for (var value of merged.values()) {
console.info(' = ' + value);
mergedArray.push(value);
}
console.info('merged', mergedArray);
// console.info(merged)
// console.info('second2', second);
// console.info('first2 ', first);
const merged = test.map(ele => {
const found = test2.find(({id}) => id === ele.id) || {}
return {...ele, ...found}
})
test
test2
(если не найден, установите пустой объект)test
является источником, а test2
содержит перезапись/дополненияхорошо, так что я считаю, что я делал неправильно... По сути, это то же самое, за исключением того, что каждый из моих идентификаторов карты является значением, поэтому, когда он объединяется, все значение при слиянии заменяется... Но мне нужно было заменить каждый объект свойства, которые вы сделали. интересно.
Если мое решение было тем, что вы искали, отметьте его как принятое или обратитесь за дополнительной помощью.
отредактировал его, чтобы он работал, даже если в test2
есть участники, которых нет в test
Попробуйте что-нибудь вроде этого.
const test = [{
id: 1,
prop: 'bill',
location: 'san diego'
}, {
id: 11,
prop: 'bright'
}, {
id: 12, //not in test2
prop: 'something',
location: 'NY'
},
{
id: 13, //no "prop" in test2
prop: 'something',
location: 'NY'
}
];
const test2 = [{
id: 1,
prop: 'casey'
}, {
id: '11',
prop: 'candle'
},
{
id: 13,
something: false
},
{
id: 100, // not in test
prop: 'other'
}
];
test.forEach(t => {
const t2 = test2.find(t2 => t2.id == t.id);//=== for exact match
if (t2)
t.prop = t2.prop || t.prop;
});
console.info(test);
Использование двойного равенства ==
— плохая идея, строковые и числовые идентификаторы будут неразличимы и объединены.
@Marcin Это сделано специально. В этом случае они должны быть неразличимы.
это не то. целостность исходного объекта должна оставаться неизменной для свойств, которые не копируются из входящего объекта
Я также хочу прояснить, почему этого недостаточно. Ваше решение зависит от утверждения, которое соответствует свойству, которое вы ищете. В то время как приведенное выше соответствует всему объекту. То, что поступает, должно переопределить, меньше оно или больше. То, что есть, не должно быть переопределено, если нет соответствующего переопределяющего свойства. И приведенное выше решение легче читать, особенно с принципом KISS, который вы предложили ранее.
как видно из фрагмента, test
обновляется еслиid
соответствует (приблизительно ==
или точно ===
) а также свойство (prop
) существует в test2
.
@AlexKudryashev, но я не хочу, чтобы он беспокоился о каком-либо свойстве объекта, кроме совпадения с идентификатором. Другие свойства должны свободно изменяться.
это именно то, что делает мой фрагмент.
Предоставление этого ответа с использованием функции Map(), чтобы сначала объекту можно было установить значение ключа. Принятый ответ краток и лаконичен, но это может иметь дополнительную ценность.
var test = [{id: 1, prop: 'bill', location: 'san diego'},{id: 11, prop: 'bright'}];
var test2 = [{id: 1, prop: 'casey'},{id: 11, prop: 'candle'}];
const map = new Map(test.map(obj => [obj.id, obj]));
for (const item of test2) {
if (map.has(item.id)) {
// map.set( item.id, item ); // replace the item value
map.set(item.id, { ...map.get(item.id),
...item
});
}
}
console.info(Array.from(map));
Применяйте принцип KISS.