mmcglynn
mmcglynn

Reputation: 7662

How can I merge the values of a multidimensional array based on a single element?

Given the following array, how do I get the distribution of years per state?

For example, look at Florida. There are 2 entries from 2021 and one from 2022.

[
    ["Arizona", 1, 2021],
    ["California", 1, 2021],
    ["Florida", 3, 2021],
    ["Florida", 3, 2022],
    ["Florida", 3, 2021],
    ["Mississippi", 1, 2022],
    ["Ohio", 3, 2021],
    ["Ohio", 3, 2022],
    ["Ohio", 3, 2023],
]

The desired output array would collapse these matching entries

  ["Florida", 3, 2021],

with the total count remaining intact. Thus, 2 + 1 = 3.

  [
    ["Florida", 2, 2021],
    ["Florida", 1, 2022],
    ["Ohio", 1, 2021],
    ["Ohio", 1, 2022],
    ["Ohio", 1, 2023],
  ]

I've tried filtering, but to no avail. is this even possible giving the input?

I tries something like the following, but I have no idea how to proceed.

let filtered = postsSummary.filter((el) => el[3].includes(2021));

console.log(filtered);

Upvotes: 0

Views: 39

Answers (1)

jsejcksn
jsejcksn

Reputation: 33739

The second element of each tuple of the input data is just noise and can be ignored. While iterating, you need to maintain a KV cache of counts keyed by the combination of state-year:

function transform (array) {
  const cache = {};

  for (const [state,, year] of array) {
    const key = JSON.stringify([state, year]);
    cache[key] = (cache[key] ?? 0) + 1;
  }

  return Object.entries(cache).map(([json, count]) => {
    const [state, year] = JSON.parse(json);
    return [state, count, year];
  })
}

const input = [
  ['Arizona', 1, 2021],
  ['California', 1, 2021],
  ['Florida', 3, 2021],
  ['Florida', 3, 2022],
  ['Florida', 3, 2021],
  ['Mississippi', 1, 2022],
  ['Ohio', 3, 2021],
  ['Ohio', 3, 2022],
  ['Ohio', 3, 2023],
];

const expected = [
  ['Arizona', 1, 2021],
  ['California', 1, 2021],
  ['Florida', 2, 2021],
  ['Florida', 1, 2022],
  ['Mississippi', 1, 2022],
  ['Ohio', 1, 2021],
  ['Ohio', 1, 2022],
  ['Ohio', 1, 2023],
];

function equalJson (a, b) {
  return JSON.stringify(a) === JSON.stringify(b);
}

const actual = transform(input);

const equal = equalJson(actual, expected);
console.log('equal:', equal);

Upvotes: 2

Related Questions