2

What I'm working with is a matrix of objects and I'm trying to find the maximum values for each of the objects, including duplicates.

Here's what I have until now:

        let findColumnMaxValue = (i) => {
         let coord = [];
         let maxValue = 0;
         for (let j = 0; j < this.field.length; j++) {
            if (this.field[i][j].dst > maxValue) {
                maxValue = this.field[i][j].dst;
            }
        }

        getMaxValueCoord(maxValue, coord, i);
        return coord;
    }

Up here I'm finding the maximum value for every row of each column.

        let getMaxValueCoord = (max, a, i) => {
         for (let j = 0; j < this.field.length; j++) {
            if (this.field[i][j].dst === max) {
                a.push({x: i, y: j})
            }
        }
    }

and in this function, after finding the max, I'm comparing each row of each column to the max value and pushing the object coordinates into an array if it meets the condition.

    findHighestDensityCells() {
     let arr = []; 
     for (let i = 0; i < this.field.length; i++) {
         arr.push(findColumnMaxValue(i));
     }

     return [].concat(...arr);
}

Now that I have an array of all the max object value coordinates for each column, I want this array to contain only the max values, including duplicates, basically repeating much of what I've done above.

What I've written above seems to take up too much code in order to solve this simple problem. Are there other methods I could use to help reduce the amount of code?

EDIT

The data is a simple object options = { dst: 0 } with a value that gets updated by another function. Therefore the rows within the columns all contain the above object, each with different values. So my matrix could look like this:

 2 3 4 5 6 6 5 4 3 2
 3 4 5 6 7 7 6 5 4 3
 4 5 6 7 8 8 7 6 5 4
 5 6 3 4 9 9 4 3 2 1
 6 7 3 4 9 9 4 3 2 1
 6 7 3 4 5 5 4 3 2 1
 5 6 3 4 5 5 4 3 2 1
 4 6 3 4 5 5 4 3 2 1
 3 5 3 4 5 5 4 3 2 1
 2 4 3 4 5 5 4 3 2 1

The desired result is getting all the maximum values within the matrix as coordinates including duplicates. In the example above this would be [9,9,9,9].

sergdenisov
  • 6,913
  • 8
  • 38
  • 56
As above so below
  • 269
  • 1
  • 2
  • 12
  • Possible duplicate of [Get largest value in multi-dimensional array javascript or coffeescript](https://stackoverflow.com/questions/11149843/get-largest-value-in-multi-dimensional-array-javascript-or-coffeescript) – bamtheboozle Sep 04 '17 at 16:19
  • if you are just looking to reduce code size look into array.map, array.reduce, or Math.max functions to help you. if you could add a sample input of mutli D array it will be easier for other to help you – Shyam Babu Sep 04 '17 at 16:39
  • Could you add your data matrix and the desired result? – sergdenisov Sep 04 '17 at 16:52
  • olease add some data and the wanted result. – Nina Scholz Sep 04 '17 at 17:08

2 Answers2

2

Check out some magic using Array.prototype.reduce(), arrow function expression, Math.max(), spread operator, Array.prototype.map(), Array.prototype.concat(), Array.prototype.filter():

const maxArray = matrix.reduce((maxArray, row, rowIndex) => {
  const max = Math.max(0, ...row.map(e => e.dst));

  return maxArray.concat(
    row.map(
      (e, i) => ({x: i, y: rowIndex, dst: e.dst})
    ).filter(e => e.dst === max)
  );
}, []);

const maxOfAll = Math.max(0, ...maxArray.map(e => e.dst));

const filteredMaxArray = maxArray.filter(
  e => e.dst === maxOfAll
).map(e => ({x: e.x, y: e.y}));

const matrix = [
  [{dst: 2}, {dst: 3}, {dst: 4}, {dst: 5}, {dst: 6}, {dst: 6}, {dst: 5}, {dst: 4}, {dst: 3}, {dst: 2}],
  [{dst: 3}, {dst: 4}, {dst: 5}, {dst: 6}, {dst: 7}, {dst: 7}, {dst: 6}, {dst: 5}, {dst: 4}, {dst: 3}],
  [{dst: 4}, {dst: 5}, {dst: 6}, {dst: 7}, {dst: 8}, {dst: 8}, {dst: 7}, {dst: 6}, {dst: 5}, {dst: 4}],
  [{dst: 5}, {dst: 6}, {dst: 3}, {dst: 4}, {dst: 9}, {dst: 9}, {dst: 4}, {dst: 3}, {dst: 2}, {dst: 1}],
  [{dst: 6}, {dst: 7}, {dst: 3}, {dst: 4}, {dst: 9}, {dst: 9}, {dst: 4}, {dst: 3}, {dst: 2}, {dst: 1}],
  [{dst: 6}, {dst: 7}, {dst: 3}, {dst: 4}, {dst: 5}, {dst: 5}, {dst: 4}, {dst: 3}, {dst: 2}, {dst: 1}],
  [{dst: 5}, {dst: 6}, {dst: 3}, {dst: 4}, {dst: 5}, {dst: 5}, {dst: 4}, {dst: 3}, {dst: 2}, {dst: 1}],
  [{dst: 4}, {dst: 6}, {dst: 3}, {dst: 4}, {dst: 5}, {dst: 5}, {dst: 4}, {dst: 3}, {dst: 2}, {dst: 1}],
  [{dst: 3}, {dst: 5}, {dst: 3}, {dst: 4}, {dst: 5}, {dst: 5}, {dst: 4}, {dst: 3}, {dst: 2}, {dst: 1}],
  [{dst: 2}, {dst: 4}, {dst: 3}, {dst: 4}, {dst: 5}, {dst: 5}, {dst: 4}, {dst: 3}, {dst: 2}, {dst: 1}],
];

const maxArray = matrix.reduce((maxArray, row, rowIndex) => {
  const max = Math.max(0, ...row.map(e => e.dst));
  
  return maxArray.concat(
    row.map(
      (e, i) => ({x: i, y: rowIndex, dst: e.dst})
    ).filter(e => e.dst === max)
  );
}, []);

const maxOfAll = Math.max(0, ...maxArray.map(e => e.dst));

const filteredMaxArray = maxArray.filter(
  e => e.dst === maxOfAll
).map(e => ({x: e.x, y: e.y}));

console.log(filteredMaxArray);
sergdenisov
  • 6,913
  • 8
  • 38
  • 56
0

You could use a single function with only one loop over the outer array and inner array with a hash table for temporary max coordinates and with a collecting array for the result.

function getMax(data) {
    return data.reduce(function (r, a, x) {
        var hash = Object.create(null),
            max = 0;

        a.forEach(function (o, y) {
            if (max <= o.dst) {
                max = o.dst;
                hash[max] = hash[max] || [];
                hash[max].push({ x, y });
            }
        });
        return r.concat(hash[max]);
    }, []);
}

var data = [[{ dst: 1 }, { dst: 2 }, { dst: 3 }], [{ dst: 4 }, { dst: 5 }, { dst: 6 }], [{ dst: 7 }, { dst: 8 }, { dst: 9 }]]

console.log(getMax(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324