frosty
frosty

Reputation: 2851

Find indexes of multiple max values in array

I have an example array:

var arr = [10, 67, 100, 100];

I want to find the indexes of the maximum values in the array.

This function finds only one index:

function max(arr) {
      var max = arr[0];
      var maxIndex = 0;
      for (var i = 1; i < arr.length; i++) {
          if (arr[i] > max) {
              maxIndex = i;
              max = arr[i];
          }
      }
      return maxIndex;
 }

How can I modify it to return an array of max indexes? In the example array above, it should return

[2, 3].

Upvotes: 6

Views: 4877

Answers (6)

JSalys
JSalys

Reputation: 179

This is solution when you find max value at fist and then indexes of all max values.

function multipleMax(arr){
	
	var maxvalue = Math.max(...arr);
	var maxIndexes = [];
	
	for(i = 0; i < arr.length; i++){
			if(arr[i] == maxvalue){
				maxIndexes.push(i);};
        };
	return maxIndexes;
};

var arr = [10, 67, 100, 100];
console.log(multipleMax(arr));

Upvotes: 0

Redu
Redu

Reputation: 26161

I would do like this;

var arr = [10, 67, 100, 100],
      m = Math.max(...arr),
  maxes = arr.reduce((p,c,i,a) => c ==  m ? p.concat(i) : p,[]);
console.log(maxes);

Upvotes: 2

user01
user01

Reputation: 901

JS's Reduce can help with this task.

// Finds maximum value across entire array
var maxArrSingle = function(arr) {
  return arr.reduce(
    function(acc,val){
      return Math.max(acc,val);
    },
    -Infinity);
}

// Find indices where array is at max
var maxArrIndexes = function(arr) {
  var max = maxArrSingle(arr);
  return arr.reduce(function(acc,val,idx) {
    if (val >= max) acc.push(idx);
    return acc;
  },[]);
}

// demos
var arr = [10, 67, 100, 100];
console.log(maxArrIndexes(arr));

var arr = [-10, -67, -100, -100, -4000, -9, -90, -90 ];
console.log(maxArrIndexes(arr));

var arr = [];
console.log(maxArrIndexes(arr));

var arr = [0];
console.log(maxArrIndexes(arr));

var arr = [0,0];
console.log(maxArrIndexes(arr));

Upvotes: 0

le_m
le_m

Reputation: 20228

Based on this runtime comparison, I propose searching for the max indices via optimized for-loop:

function max(arr) {
  var max = -Infinity, indices = [];
  for (var i = 0; i < arr.length; ++i) {
    if (arr[i] < max) continue;
    if (arr[i] > max) {
      indices = [];
      max = arr[i];
    }
    indices.push(i);
  }
  return indices;
}

console.log(max([10, 67, 100, 100])); // [2, 3]

Comparing against arr[i] < max first is useful since it evaluates to true most of the time and thus enables us to skip to the next iteration with only 1 array access + comparison on average.

Runtime comparison of the different proposed algorithms:

According to https://jsfiddle.net/jv1z29jm/2/ - please feel free to update.

  • Chrome (48):

    max_indexOf x 15,381 ops/sec ±2.94% (87 runs sampled)
    max_reduce x 2,909 ops/sec ±2.63% (86 runs sampled)
    max_forloop x 119,964 ops/sec ±1.80% (87 runs sampled)
    max_forloopOptimized x 165,581 ops/sec ±1.50% (87 runs sampled)
    Fastest is max_forloopOptimized
    
  • Firefox (46):

    max_indexOf x 56,456 ops/sec ±0.74% (67 runs sampled)
    max_reduce x 74,959 ops/sec ±0.86% (65 runs sampled)
    max_forloop x 73,223 ops/sec ±24.75% (58 runs sampled)
    max_forloopOptimized x 84,567 ops/sec ±9.99% (61 runs sampled)
    Fastest is max_forloopOptimized
    

Upvotes: 0

user94559
user94559

Reputation: 60143

Instead of keeping track of just one index, you'll need to keep track of all indices. Give this a try:

function max(arr) {
    var max = -Infinity;
    var maxIndices = [];
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] === max) {
          maxIndices.push(i);
        } else if (arr[i] > max) {
            maxIndices = [i];
            max = arr[i];
        }
    }
    return maxIndices;
 }

Upvotes: 3

Midas
Midas

Reputation: 7131

function max(arr) {
    var largest = Math.max.apply(Math, arr);

    var indexes = [], i = -1;
    while ((i = arr.indexOf(largest, i+1)) != -1){
        indexes.push(i);
    }
    return indexes;
}

var arr = [10, 67, 100, 100];
console.log(max(arr));

Upvotes: 1

Related Questions