Home > Software design >  Reduce nested array maximum values to a single array
Reduce nested array maximum values to a single array

Time:08-04

I am trying to find a way to reduce the max values of specific positions/indexes within nested arrays into a single array.

Given:

const myArr = [[105,87,171],[113,192,87],[113,87,87],[113,87,87]]

Expected return value:

[113,192,171]

Actual return value:

[113,87,87]

Using the following code, I'm getting the above return value.

const highest = myArr.reduce((previous, current) => {
  return current > previous ? current : previous;
});

Why am I only getting the max value for the first position, and not the remaining two positions of the nested arrays?

CodePudding user response:

Why am I only getting the max value for the first position, and not the remaining two positions of the nested arrays?

Because in your code:

const highest = myArr.reduce((previous, current) => {
  return current > previous ? current : previous;
});

both current and previous are single elements of your array myArr - which means they are themselves 3-element arrays. You're basically computing the maximum array - which doesn't really make sense, although Javascript's type coercion will always find some away. I believe here it's converting the arrays to strings which effectively means it will return the one with the "highest" first element, then the "highest" second if tied and so on, where "highest" here will be when comparing as strings. I could be wrong about that, but in any case note the return value is indeed one of the subarrays in your array - and this is clearly not what you need.

If you want to compute this with a single reduce call - because it is most performant to only traverse the array once, although that's not going to matter in practice with an array of only 3 elements - you have to keep track of the maximum you've had at each of the 3 indices. So it would look something like this:

const myArr = [[105,87,171],[113,192,87],[113,87,87],[113,87,87]];

const highest = myArr.reduce((previous, current) => {
  const highest0 = Math.max(previous[0], current[0]);
  const highest1 = Math.max(previous[1], current[1]);
  const highest2 = Math.max(previous[2], current[2]);
  return [highest0, highest1, highest2];
});

console.log(highest);

Although if performance isn't an issue and readability is a priority, you might prefer to simply map the array 3 times to get one array for each of the 3 positions, then find the maximum of each array (which you can easily do with Math.max and spreading the array as arguments).

CodePudding user response:

You need to compare the elements in subarrays by index.

const myArr = [[105,87,171],[113,192,87],[113,87,87],[113,87,87]]

const highest = myArr.reduce((previousArr, currentArr) => {
    return previousArr.map((item, index) =>
        Math.max(item, currentArr[index])
    )
});

console.log(highest)

CodePudding user response:

Here's how to do it with Array#reduce and Math.max methods:

const myArr = [[105,87,171],[113,192,87],[113,87,87],[113,87,87]],
    
      output = myArr.reduce(
          ([x,y,z],[a,b,c]) => 
          [
              Math.max(x,a),
              Math.max(y,b),
              Math.max(z,c)
          ]
      );
      
console.log( output );

Alternatively...

You can add Array#map to the mix to create a more general solution:

const myArr = [[105,87,171],[113,192,87],[113,87,87],[113,87,87]],
    
      output = myArr.reduce(
          (acc,cur) => 
          cur.map((c,i) => Math.max(c, acc[i]))
      );
      
console.log( output );

So...

Rewriting your solution ....

const myArr = [[105,87,171],[113,192,87],[113,87,87],[113,87,87]];

const highest = myArr.reduce((previous, current) => {
  return current.map((cur,i) => cur > previous[i] ? cur : previous[i]);
});

console.log( highest );

  • Related