Concat объект с новыми значениями и преобразовать его в массив - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть такой случай: я выдвигаю к объекту новые key-value пары, например:

let a1 = {key1: 'val1'};
let a2 = {key2: 'val2'};
const result = {...a1, ...a2};

и в результате я получаю новый действительный объект: {key1: 'val1', key2: 'val2'}.

но есть третий случай:

let a1 = {key1: 'val1'};
let a2 = {key2: 'val2'};
let b1 = {key1: 'val1b'};
const result = {...a1, ...a2, ...b1};

и в результате я должен получить:

{key1: ['val1', 'var1b'], key2: 'val2'}`.

so -> если такой ключ уже существует -> преобразовать значения этого ключа в массив и передать их.

Я пытался так:

для ... всех моих объектов, чтобы нажать:

const keysToPush = Object.keys(b1);
const keysInitial = Object.keys(a1); // foreach too
if (keysInitial.includes(keysToPush)) // push as array

но выглядит уродливо

наверное, должно быть более элегантное решение?

Ответы [ 4 ]

1 голос
/ 29 апреля 2019

Я бы предложил использовать Map (для ключей) или Set (для значений на ключ), так как Set не обеспечит дублирование значений.В конце процесса Map может быть преобразован в простой объект, а Set в одно значение или массив значений:

// Sample input with some repetition:
const objects = [
    { key1: 'val1' },
    { key2: 'val2' },
    { key1: 'val1b' },
    { key2: 'val2' },
    { key1: 'val1b' }
];

const pairs = objects.flatMap(Object.entries);
const map = new Map(pairs.map(([k]) => [k, new Set]));
pairs.forEach(([k, v]) => map.get(k).add(v));
const result = Object.fromEntries(Array.from(map, ([k, set]) => 
   set.size < 2 ? [k, ...set] : [k, [...set]]
));

console.log(result);
1 голос
/ 29 апреля 2019

Проверьте, существует ли ключ.Если это так, проверьте, является ли это массив, и обработайте каждый случай соответственно:

let a1 = {
  key1: 'val1'
};
let a2 = {
  key2: 'val2'
};
let b1 = {
  key1: 'val1b'
};

const merge = (...o) => {
  let res = o.reduce((acc, curr) => {
    Object.entries(curr).forEach(([k, v]) => {
      acc[k] = (acc[k] && Array.isArray(acc[k]) ? [...acc[k], v] : (acc[k] ? [acc[k], v] : v));
    });
    return acc;
  });
  return res;
};

let result = merge(a1, a2, b1);
console.log(result);
.as-console-wrapper {
  max-height: 100% !important;
  top: auto;
}
1 голос
/ 29 апреля 2019

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

const
    migrate = (target, source) => {
        Object.keys(source).forEach(key => {
            if ([].concat(target[key] || []).includes(source[key])) return;
            if (key in target) {
                if (!Array.isArray(target[key])) target[key] = [target[key]];
                target[key].push(source[key]);
            } else {
                target[key] = source[key];
            }
        });
        return target;
    };

var a1 = { key1: 'val1' },
    a2 = { key2: 'val2' },
    b1 = { key1: 'val1b' },
    b2 = { key1: 'val1b' },
    result = [a1, a2, b1, b2].reduce(migrate, {});

console.log(result);
0 голосов
/ 29 апреля 2019

Вы можете создать функцию для объединения объектов. Шаги решения:

  • Создать функцию, которая принимает любое количество объектов, используя параметры отдыха
  • Создайте пустой объект, который будет результатом.
  • Обведите все объекты, используя forEach. Внутри forEach создайте еще один вложенный forEach для циклического просмотра записей объекта.
  • Проверьте, существует ли ключ в результате obj.

    • Проверьте, являются ли его значения массивом, затем введите в него новое значение.

    • Если это не массив, просто преобразовать его в массив из двух значений

  • Если ключ не существует, обычно добавьте его как ключ объекта.

function mergeObjs(...objs){
  const res = {};
  objs.forEach(x => {
    Object.entries(x).forEach(([k,v]) => {
      if(res[k]){
        if(Array.isArray(res[k])) res[k].push(v)
        else res[k] = [res[k],v]
      }
      else res[k] = v;
    })
  })
  return res;
}

let a1 = {key1: 'val1'};
let a2 = {key2: 'val2'};
let b1 = {key1: 'val1b'};

console.log(mergeObjs(a1,a2,b1))
...