Преобразование массива кортежей с двумя входами в объект, который сопоставляет каждый ключ с массивом значений

#javascript #node.js

#javascript #node.js

Вопрос:

Учитывая массив кортежей с двумя входами, например:

 const arr = [
    ['key1', 'value1'],
    ['key2', 'value2'],
    ['key3', 'value3'],
    ['key2', 'value4'],
    ['key3', 'value5'],
    ['key3', 'value6']
];
 

Я ищу аккуратный способ получить:

 const obj = {
    key1: ['value1'],
    key2: ['value2', 'value4'],
    key3: ['value3', 'value5', 'value6']
};
 

Пока у меня есть:

 const obj = Object.assign({}, ...arr.map(x => ({[x[0]]: x[1]})));
 

Что дает мне:

 const obj = {
    key1: 'value1',
    key2: 'value4',
    key3: 'value6'
};
 

Я чувствую, что могу как-то использовать reduce для получения желаемого результата.

Я использую NodeJS (не браузер).

Ответ №1:

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

 const arr = [["key1","value1"],["key2","value2"],["key3","value3"],["key2","value4"],["key3","value5"],["key3","value6"]]

const result = arr.reduce((r, [k, v]) => {
  if (!r[k]) r[k] = [v]
  else r[k].push(v)
  return r
}, {})

console.log(result) 

Ответ №2:

Reduce — идеальный вариант использования здесь

 const arr = [
    ['key1', 'value1'],
    ['key2', 'value2'],
    ['key3', 'value3'],
    ['key2', 'value4'],
    ['key3', 'value5'],
    ['key3', 'value6']
];

const res = arr.reduce((acc, [key, value]) => {
  // Create the key:value and append new value
  acc[key] = acc[key] || [];
  acc[key] = [...acc[key], value];
  return acc;
}, {});

console.log(res) 

Комментарии:

1. Итак const res = arr.reduce((acc, [key, value]) => ({[...(acc[key] || []), value]}), {}); ?

2. Я бы избегал нечитаемого кода. Было бы здорово сократить 6 строк кода до 1, но это невозможно поддерживать. 🙂

Ответ №3:

Вы могли бы использовать объект Map .

 const arr = [
  ['key1', 'value1'],
  ['key2', 'value2'],
  ['key3', 'value3'],
  ['key2', 'value4'],
  ['key3', 'value5'],
  ['key3', 'value6'],
];

const map = new Map();
arr.forEach(([x, y]) => map.set(x, map.has(x) ? [...map.get(x), y] : [y]));
const ret = Object.fromEntries(map.entries());
console.log(ret);