Как склеить элементы массива в один, суммировав некоторое значение, при определенных условиях в js?

Есть массив, где каждый элемент тоже массив:

let arr = [
  ['orange', '2021-07-01', 100],
  ['apple', '2021-07-01', 100],
  ['orange', '2021-07-01', 400],
  ['apple', '2021-07-06', 100],
  ['apple', '2021-07-01', 400],
];

Необходимо все подмассивы, где совпадают первые два значения, склеить в один, суммировав их третье значение.
То есть, на выходе должен получиться массив где склеены подмассивы с индексами 0 и 2, а также 1 и 4:

[
  ['orange', '2021-07-01', 500],
  ['apple', '2021-07-01', 500],
  ['apple', '2021-07-06', 100],
]

Ответы (2 шт):

Автор решения: yar85

Можно сначала посчитать суммы в хэштаблицу (где ключами является объединение некоторых значений) - а затем преобразовать ее обратно в массив (с разбором каждого ключа обратно в значения). Итого два прохода. А точнее, один проход по данным, и один по хэштаблице:

let arr = [
  ['orange', '2021-07-01', 100],
  ['apple', '2021-07-01', 100],
  ['orange', '2021-07-01', 400],
  ['apple', '2021-07-06', 100],
  ['apple', '2021-07-01', 400],
];

const merged = arr.reduce((rslt, [fruit, date, value]) => {
  const key = [fruit, date].join('|');
  rslt[key] = (rslt[key] || 0) + value;
  return rslt;
}, Object.create(null));

const reconstructed = Object.entries(merged).map(
  ([key, value]) => [...key.split('|'), value]
);

console.log(reconstructed);

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

Тот же самый подход может быть применен с любым (≥2) количеством ключевых значений, с массивами объектов (а не только с массивом подмассивов), и т.д..

→ Ссылка
Автор решения: Stanislav Volodarskiy

Нужен ключ из пары значений. К сожалению, JavaScript допускает в качестве ключей только строки и числа. Даже Map не поможет - он принимает массивы в качестве ключей но сравнивает их не по значению.

JSON.stringify преобразует массив в строку гарантируя что разные по значению массивы породят разные строки. В словаре хранятся целиком записи (фрукт/дата/значение), не только значения. Фрукт и дату можно было бы восстановить из ключа, я так не делаю, чтобы не добавлять ещё одну сложную операцию:

const merge = a => {
    const map = Object.create(null);
    for (const [fruit, date, value] of a) {
        const key = JSON.stringify([fruit, date]);
        const record = map[key];
        if (record === undefined) {
            map[key] = [fruit, date, value];
        } else {
            record[2] += value
        }
    }
    return Object.values(map);
};

console.log(merge([
  ['orange', '2021-07-01', 100],
  ['apple', '2021-07-01', 100],
  ['orange', '2021-07-01', 400],
  ['apple', '2021-07-06', 100],
  ['apple', '2021-07-01', 400],
]));

→ Ссылка