Как сжать массив объектов по идентификатору? - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть массив предметов:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

И я хотел бы создать объект из элементов id:

const obj = {
  abc: { id: 'abc', value: 2 },
  def: { id: 'def', value: 3 },
};

Насколько я знаю, самый эффективный и лаконичный способ сделать это через Array.prototype.reduce

const obj = arr.reduce((obj, entry) => {
  obj[entry.id] = entry;
  return obj;
}, {});

Существуют ли более эффективные и более краткие способы выполнения операции? Что они?

Я знаю, что это относительно субъективно, и я открыт для предложений, как мне лучше сформулировать вопрос. Благодаря.

1 Ответ

3 голосов
/ 10 апреля 2019

Вы можете сделать его однострочным, используя оператор запятой :

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = arr.reduce((obj, entry) => (obj[entry.id] = entry, obj), {});

console.log(obj);

Это менее читабельно, но несколько более кратко.Это зависит от вас, если оно того стоит.Так как вы упомянули, что вы заинтересованы в распространения , вот это решение, но производительность смотрите ниже:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = arr.reduce((obj, entry) => ({ ...obj, [entry.id]: entry }), {});

console.log(obj);

Еще одно решение, использующее расширение аргументов с помощью Object.assign, но этот код кажется мне немного неуклюжим, а производительность ниже:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = Object.assign({}, ...arr.map(a => ({ [a.id]: a })));

console.log(obj);

Что касается наиболее производительного решения, то трудно победить for -loops:

const arr = [
  { id: 'abc', value: 2 },
  { id: 'def', value: 3 },
];

const obj = {}, len = arr.length;
for(let i = 0; i < len; i++) {
  let a = arr[i];
  obj[a.id] = a;
}

console.log(obj);

Быстрый тест на моей машине дал следующие результаты (на Firefox 66):

test case     | ops/s             | result
reduce-comma  | 22,248,622 ±2.83% |  6.89% slower
reduce-spread |  4,149,590 ±2.84% | 82.63% slower
object-assign |  1,809,170 ±0.69% | 92.43% slower
for-loop      | 23,895,193 ±2.51% | fastest

Второе решение намного медленнее из-за использованияоператора распространения объекта, который клонирует объект на каждой итерации.Я, честно говоря, не уверен, почему Object.assign еще медленнее, поскольку большинство реализаций распространения объектов находятся под Object.assign под крышками.

Разница между двумя последними вариантами составляет miniscule ,но это может быть более важно в старых браузерах, которые не так хорошо оптимизированы.Я бы порекомендовал вам запустить собственные тесты, если это действительно приложение, критичное к производительности.

...