Skip to content

Instantly share code, notes, and snippets.

@engelen
Last active March 7, 2023 01:32
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save engelen/fbce4476c9e68c52ff7e5c2da5c24a28 to your computer and use it in GitHub Desktop.
Save engelen/fbce4476c9e68c52ff7e5c2da5c24a28 to your computer and use it in GitHub Desktop.
Single-line ArgMax for JavaScript
/**
* Retrieve the array key corresponding to the largest element in the array.
*
* @param {Array.<number>} array Input array
* @return {number} Index of array element with largest value
*/
function argMax(array) {
return array.map((x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1];
}
console.log(argMax([ 5.2, 1.4, 9.6, 1.8, 3.2, 2.4 ]));
// Output: 2
@kl23
Copy link

kl23 commented Feb 12, 2019

Note that for TypedArray, it fails as the map function returns a new Array of its original type.

@FarisHijazi
Copy link

Thank you for the snippet, I found this handy.
As you know, the world of JavaScript contains many iterables that don't contain map. I've tweaked your function to work with any iterable:

function argMax(array) {
  return [].map.call(array, (x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1];
}

@byildiz
Copy link

byildiz commented Mar 6, 2020

Thank you. It also gives me the idea of a method that runs without first converting [value, index] array:

function argMax(array) {
  return [].reduce.call(array, (m, c, i, arr) => c > arr[m] ? i : m, 0)
}

Edit after the @ulrych8's comment: call reduce with an initial value.

@upavloff
Copy link

@byildiz your function doesn't seem to be working when the array has a length of 2

@byildiz
Copy link

byildiz commented May 21, 2020

@ulrych8 thank you for spotting the bug. I editted the code.

@FelixBenning
Copy link

FelixBenning commented Jul 24, 2022

If you want to collect all the indices where the array is maximal, then this should work:

/**
 * Find List of ArgMax, empty if list is empty 
 * @param array iterable
 * @returns all indices where the Array has the maximal value
 */
export function argMax(array): number[] {
  return [].reduce.call(
    array,
    (aMax: number[], current, idx: number, arr: any[]) => {
      // for idx=0, aMax is empty, arr[0] === current, 0 is pushed, then never empty again
      const max = arr[aMax[0] || 0]; 
      if (current > max) return [idx];
      if (max === current) aMax.push(idx);
      return aMax;
    },
    []
  );
}

@Gio-Mgm
Copy link

Gio-Mgm commented Aug 17, 2022

With dictionnary-like object you can also do this :

// with [0] at the end it return only the key, without it, it return [maxKey, maxValue]
const argMax = obj => Object.entries(obj).reduce((a, r) => a[1] > r[1] ? a : r)[0] 

// or if you need key value and index:
const argMax = obj => Object.entries(obj).map(([k, v], idx) => [k, v, idx]).reduce((a, r) => a[1] > r[1] ? a : r)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment