Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combine sub-arrays by using as a key a sub-string found in the first element of each sub-array

Having a bi-dimensional array of this form:

arr = [
        ["12325-a", 1, 1, 1],
        ["43858-b", 3, 4, 1],
        ["84329-a", 6, 5, 2],
        ["18767-b", 0, 9, 0],
        ["65888-b", 5, 4, 4],
];

On each sub-array the first element is a string.

I want to combine together the sub-arrays having the same end. In this case it will be two groups : -a and -b.

The numerical values should be computed as sum based on idex.

So the result would look like:

arr = [
        ["-a", 7, 6, 3],
        ["-b", 8, 17, 5],
];

my solution (which does not work):

let arr = [
  ["12325-a", 1, 1, 1],
  ["43858-b", 3, 4, 1],
  ["84329-a", 6, 5, 2],
  ["18767-b", 0, 9, 0],
  ["65888-b", 5, 4, 4],
];

result = arr.reduce(function(acc, curr) {
  if (acc[curr[0].substr(curr[0].length - 2)]) {
    acc[curr[0]] = acc[curr[0]].map(function(val, index) {

      if (index) {
        return val + curr[index];
      }
      return val;
    });
  } else {
    acc[curr[0]] = curr;
  }
  return acc;
}, {});

console.log(result)
like image 576
Leo Messi Avatar asked Jul 26 '18 10:07

Leo Messi


2 Answers

You could first use reduce method to create an object and then Object.values to get an array of values.

const arr = [
    ["12325-a", 1, 1, 1],
    ["43858-b", 3, 4, 1],
    ["84329-a", 6, 5, 2],
    ["18767-b", 0, 9, 0],
    ["65888-b", 5, 4, 4],
];

const result = arr.reduce((r, [str, ...rest]) => {
  let key = str.split(/(\d+)/).pop();
  if(!r[key]) r[key] = [key, ...rest];
  else rest.forEach((e, i) => r[key][i + 1] += e)
  return r;
}, {})

console.log(Object.values(result))
like image 130
Nenad Vracar Avatar answered Oct 24 '22 07:10

Nenad Vracar


You aren't using the correct key while checking for existing value and mapping over the existing data. Your solution would look like

let arr = [
  ["12325-a", 1, 1, 1],
  ["43858-b", 3, 4, 1],
  ["84329-a", 6, 5, 2],
  ["18767-b", 0, 9, 0],
  ["65888-b", 5, 4, 4],
];

result = arr.reduce(function(acc, curr) {

  const key = curr[0].substr(curr[0].length - 2);
  console.log(key)
  if (acc[key]) {
    acc[key] = acc[key].map(function(val, index) {

      if (index) {
        return val + curr[index];
      }
      return val;
    });
  } else {
    acc[key] = [curr[0].substr(curr[0].length - 2), ...curr.slice(1)]
  }
  return acc;
}, {});

console.log(Object.values(result));
like image 3
Shubham Khatri Avatar answered Oct 24 '22 05:10

Shubham Khatri