Слияние двух JavaScript объектов и конфликтующих свойств - PullRequest
1 голос
/ 10 апреля 2020

Скажем, у меня есть два объекта:

var obj1 = {cars: 'ford', fruit: 'peach', other: ['bar']}
var obj2 = {cars: 'ferrari', info: 'foo', other: ['baz']}

Теперь я хочу объединить эти два объекта и любые конфликтующие свойства. Ожидаемый результат:

{cars: ['ford', 'ferrari'], fruit: 'peach', info: 'foo', other: ['bar', 'baz']}

Тем не менее, при использовании разброса объектов

{...obj1, ...obj2}

Возвращает

{cars: 'ferrari', fruit: 'peach', info: 'foo', other: ['baz']}

Есть ли способ объединить два объекта и объединить конфликтующие свойства в массивы вместо переопределения? Примечание: мне нужен чистый JS

Ответы [ 4 ]

0 голосов
/ 10 апреля 2020

Вот моя версия:)

var obj1 = {cars: 'ford', fruit: 'peach', other: ['bar']}
var obj2 = {cars: 'ferrari', info: 'foo', other: ['baz']}

var merge = (acc, [k, v]) => {
  if (k in acc) {
    acc[k] = [acc[k]].flat().concat(v)
  } else {
    acc[k] = v;
  }

  return acc;
}

var res = Object.entries(obj1).reduce(merge, obj2);
0 голосов
/ 10 апреля 2020

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

var obj1 = {cars: 'ford', fruit: 'peach', other: ['bar']}
var obj2 = {cars: 'ferrari', info: 'foo', other: ['baz']}

function merge(obj1, obj2) {
    let result = Object.assign({}, obj1);
    for (let [key, value] of Object.entries(obj2)) {
        if (result.hasOwnProperty(key)) {
            if (!Array.isArray(result[key])) {
                // target isn't an array yet, have to convert it to an array
                result[key] = [result[key]];
            }
            // now copy over either a single entry or an array of entries
            if (Array.isArray(obj2[key])) {
                // copy all the array entries over to the other array
                result[key].push(...obj2[key]);
            } else {
                // copy single entry over to the other array
                result[key].push(obj2[key]);
            }
        } else {
            // result doesn't have this property yet, just copy the value over
            result[key] = value;
        }
    }
    return result;
}

console.log(merge(obj1, obj2));
0 голосов
/ 10 апреля 2020

Это тоже должно работать:

function mergeObject(o1, o2) {
  return {
    ...o2,
    ...Object.keys(o1).reduce((r, c) => ({
      ...r, [c]: o2.hasOwnProperty(c) ? [
        ...(Array.isArray(o1[c]) ? o1[c] : [o1[c]]),
        ...(Array.isArray(o2[c]) ? o2[c] : [o2[c]]),
      ] : o1[c]
    }), {})
  }
}

var obj1 = { cars: 'ford', fruit: 'peach', other: ['bar'] }
var obj2 = { cars: 'ferrari', info: 'foo', other: ['baz'] }
const result = mergeObject(obj1, obj2)
console.log(result)
0 голосов
/ 10 апреля 2020

Вы можете объединить по свойству и проверить, не является ли цель массивом или значение thje является массивом.

const
    merge = (target, source) => Object.entries(source).reduce((o, [k, v]) => {
        if (k in o) {
            if (!Array.isArray(o[k])) o[k] = [o[k]];
            [].concat(v).forEach(item => {
                if (!o[k].includes(item)) o[k].push(item);
            });
        } else {
            o[k] = v;
        }
        return o;
    }, target);

var obj1 = { cars: 'ford', fruit: 'peach', other: ['bar'] },
    obj2 =  {cars: 'ferrari', info: 'foo', other: ['baz'] },
    result = [obj1, obj2].reduce(merge, {});

console.log(result);
...