Nikita Kobtsev
Nikita Kobtsev

Reputation: 153

Fast way to find index of max/min element in Nth column of matrix

I am trying to get the index of the maximum and minimum element of a specific column in the matrix. Now I am doing as follows using ES6 and Spread syntax:

a = [
  [22,23],
  [74,1],
  [21,33],
  [32,84],
  [11,31],
  [1,49],
  [7,8],
  [11,11],
  [99,68],
  [52,20]
];

const minValue = (arr, n) => Math.min(...arr.map(x => x[n])); //n - column index
const maxValue = (arr, n) => Math.max(...arr.map(x => x[n]));

const minValueIndex = (arr, n) => arr.map(x => x[n]).indexOf(minValue(arr, n));
const maxValueIndex = (arr, n) => arr.map(x => x[n]).indexOf(maxValue(arr, n));

console.log(minValue(a, 0));
console.log(maxValue(a, 0));

console.log(minValueIndex(a, 0));
console.log(maxValueIndex(a, 0));

But at the same time too many comparisons are made, I do not think that this is the best way to complete this task. I would be glad to see faster implementations using the ES6 standard or without it.

Upvotes: 2

Views: 559

Answers (3)

Sajeeb Ahamed
Sajeeb Ahamed

Reputation: 6390

You are almost there and you are just concern about the performance right? So for improving the performance of your program, you can use a nice technique called Memoization

Memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again

const arr = [[22,23], [74,1], [21,33], [32,84], [11,31], [1,49], [7,8], [11,11], [99,68], [52,20]];

/**
* Here I create the momoized function which cache the
* column and if we want to get the same column then it
* simply return the previously cached column array
* otherwise, it get the column and cache it for future
* and return it.
*/
const memoized = () => {
	const cache = {};

	return (arr, index) => {
	    if (index in cache) {
	        return cache[index];
	    } else {
		const col = arr.map(item => (item[index]));
		cache[index] = col;
		return col;
	    }
	}
}

/**
* As memoized is a higher order function so it returns
* another function which will be executed by calling
* this getColumn function reference.
*/
const getColumn = memoized();

const getMinValue = (arr, col) => Math.min(...getColumn(arr, col));
const getMaxValue = (arr, col) => Math.max(...getColumn(arr, col));

const minValueIndex = (arr, col) => getColumn(arr, col).indexOf(getMinValue(arr, col));
const maxValueIndex = (arr, col) => getColumn(arr, col).indexOf(getMaxValue(arr, col));

console.log('minValue: ', getMinValue(arr, 0)); // Calculated
console.log('maxValue: ',getMaxValue(arr, 0)); // Cached

console.log('minValueIndex: ', minValueIndex(arr, 0)); // Cached
console.log('maxValueIndex: ', maxValueIndex(arr, 0)); // Cached
.as-console-wrapper {min-height: 100% !important; top: 0;}

Upvotes: 1

Husnain Tariq
Husnain Tariq

Reputation: 154

Will this help?

let a = [
    [22, 23],
    [74, 1],
    [21, 33],
    [32, 84],
    [11, 31],
    [1, 49],
    [7, 8],
    [11, 11],
    [99, 68],
    [52, 20]
];
let max = 0,
    min = 0,
    minIndex = 0,
    maxIndex = 0;

const findValue = (array, col) => {
    array.map((matrix) => {
        (matrix[col] > max) ? max = matrix[col]: null;
        (min == 0) ? min = max: null;
        (matrix[col] < min) ? min = matrix[col]: null;
    })
}
const findIndex = (array, col, min, max) => {
    minIndex = array.map(data => data[col]).indexOf(min);
    maxIndex = array.map(data => data[col]).indexOf(max);
}

findValue(a, 0)
findIndex(a, 0, min, max);
console.log(min, max, minIndex, maxIndex);

Upvotes: 1

Moritz Roessler
Moritz Roessler

Reputation: 8611

A simple solution would be to loop over the array and store the min/max values in a temporary variable.

function minMax (arr, n) {
    let min=Infinity, max=0;
    for (const _arr of arr) {
        const x = _arr[n];
        if (x < min) min = x;
        if (x > max) max = x;
    }
    return [min, max];
}

function minMaxIndex (arr, n) {
    let min=Infinity, max=0, minIndex, maxIndex;
    for (let i=0; i < arr.length; i++) {
        const x = arr[i][n];
        if (x < min) {
          min = x;
          minIndex = i;
        }
        if (x > max) {
          max = x;
          maxIndex = i;
        }
    }
    return [minIndex, maxIndex];
}

console.log (minMax(a, 0))
console.log (minMaxIndex(a, 0))
<script>
a = [
  [22,23],
  [74,1],
  [21,33],
  [32,84],
  [11,31],
  [1,49],
  [7,8],
  [11,11],
  [99,68],
  [52,20]
];
</script>

Upvotes: 1

Related Questions