Retourne l'index de la plus grande valeur dans un tableau

139

J'ai ceci:

var arr = [0, 21, 22, 7];

Quelle est la meilleure façon de renvoyer l'index de la valeur la plus élevée dans une autre variable?

Stephen
la source
21
Ce n'est pas un doublon, lisez la question… @Dancrumb La façon dont SO fonctionne est que je poste cette question et pendant des décennies, les gens la trouveront, la liront et seront reconnaissantes pour les informations que les contributeurs ont postées ci-dessous!
Stephen
1
@Stephen, au contraire, si vous lisez cette FAQ , vous verrez que les questions subjectives (comme celles qui commencent "Quelle est la meilleure façon ...") sont expressément déconseillées. Cependant, SO est une communauté, c'est donc à la communauté de déterminer si cette question doit être close ou non.
Dancrumb
6
Trouver le plus grand nombre dans un tableau n'est pas la même chose que trouver l'index du plus grand nombre dans un tableau. Par conséquent, cette question n'est pas un double de cette référence publiée en double.
Fzs2
15
Ce n'est PAS un doublon - ou du moins pas de la question référencée. Je ne peux pas comprendre les votes négatifs à ce sujet - dire que vous ne pouvez pas demander à SO la meilleure façon de faire quelque chose est ridicule, et aucun exemple de code n'est requis pour une question aussi concise. Comment se fait-il que le «doublon» référencé ait +30 voix, et que cette question parallèle MAIS DIFFÉRENTE, posée dans un style très similaire, ait -3 voix? Veuillez relire la question et supprimer vos votes marqués comme doublons. «index de» est la phrase clé que vous devez repérer dans le titre de la question.
pancake
@Dancrumb Le conseil actuel de stackoverflow.com/help/dont-ask décourage les questions subjectives uniquement si chaque réponse est également valable. Dans ce cas, «meilleur» peut clairement être évalué en termes de performance, de concision et d'expressivité.
user234461

Réponses:

165

C'est probablement le meilleur moyen, car il est fiable et fonctionne sur les anciens navigateurs:

function indexOfMax(arr) {
    if (arr.length === 0) {
        return -1;
    }

    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;
}

Il y a aussi ce one-liner:

let i = arr.indexOf(Math.max(...arr));

Il effectue deux fois plus de comparaisons que nécessaire et lancera un RangeErrorsur les grands tableaux, cependant. Je m'en tiendrai à la fonction.

Ry-
la source
1
Ok cette fonction retourne le premier index rencontré pour la plus grande valeur. Disons que j'ai plus d'un index avec la même valeur la plus élevée, comment puis-je obtenir tous ces index?
ed1nh0
1
@ ed1nh0: Le moyen le plus simple est de faire plusieurs passes. Trouvez le max avec const max = arr.reduce((m, n) => Math.max(m, n)), puis les index du max sont [...arr.keys()].filter(i => arr[i] === max).
Ry-
[...arr.keys()]unexpected token
renvoie
@ ed1nh0: Quel navigateur / environnement ciblez-vous?
Ry-
Chrome. J'utilise VueJS et je suppose que le problème est lié à la configuration du pack Web.
ed1nh0
82

En une ligne et probablement plus rapide alors arr.indexOf(Math.max.apply(Math, arr)):

var a = [0, 21, 22, 7];
var indexOfMaxValue = a.reduce((iMax, x, i, arr) => x > arr[iMax] ? i : iMax, 0);

document.write("indexOfMaxValue = " + indexOfMaxValue); // prints "indexOfMaxValue = 2"

Où:

  • iMax- le meilleur index jusqu'à présent (l'index de l'élément max jusqu'à présent, à la première itération iMax = 0car le deuxième argument de reduce()est 0, nous ne pouvons pas omettre le deuxième argument dereduce() dans notre cas)
  • x - l'élément actuellement testé du tableau
  • i - l'indice actuellement testé
  • arr- notre tableau ( [0, 21, 22, 7])

À propos de la reduce()méthode (extrait de "JavaScript: The Definitive Guide" de David Flanagan):

réduire () prend deux arguments. La première est la fonction qui effectue l'opération de réduction. La tâche de cette fonction de réduction est de combiner ou de réduire d'une manière ou d'une autre deux valeurs en une seule valeur et de renvoyer cette valeur réduite.

Les fonctions utilisées avec Reduce () sont différentes des fonctions utilisées avec forEach () et map (). Les valeurs familières de valeur, d'index et de tableau sont transmises en tant que deuxième, troisième et quatrième arguments. Le premier argument est le résultat cumulé de la réduction jusqu'à présent. Lors du premier appel à la fonction, ce premier argument est la valeur initiale que vous avez passée en tant que deuxième argument à réduire (). Lors des appels suivants, il s'agit de la valeur renvoyée par l'appel précédent de la fonction.

Lorsque vous appelez reduction () sans valeur initiale, il utilise le premier élément du tableau comme valeur initiale. Cela signifie que le premier appel à la fonction de réduction aura les premier et deuxième éléments du tableau comme premier et deuxième arguments.

traxium
la source
12
@traxium Bien que votre explication soit excellente, l'exemple pourrait être plus clair pour ceux qui s'intéressent moins à la programmation fonctionnelle si nous utilisons des variables plus descriptives. Dis: arr.reduce((bestIndexSoFar, currentlyTestedValue, currentlyTestedIndex, array) => currentlyTestedValue > array[bestIndexSoFar] ? currentlyTestedIndex : bestIndexSoFar, 0);qui peut être décrite comme suit: iterate la matrice à partir de l' indice 0 (deuxième paramètre), si currentlyTestedValue est supérieure à la valeur de l'élément à l' bestIndexSoFar , puis retourner le currentlyTestedIndex à l'itération suivante en tant que bestIndexSoFar .
niieani
1
@traxium Réponse géniale. Je suis d' accord aussi avec @niieani Voici un exemple du monde réel que je mis en œuvre: this.methods.reduce((methodIndex, currentMethod, currentMethodIndex, methods) => currentMethod.price <= methods[methodIndex].price ? currentMethodIndex : methodIndex, 0).
Daniel
2
@DanielK, La réponse avec les noms de paramètres "complets" ne rentrerait pas dans une seule ligne de stackoverflow. Il apparaîtrait une barre de défilement horizontale et il ne serait pas très pratique de lire l'extrait de code tout en faisant défiler horizontalement. En tout cas merci pour les suggestions. J'ai modifié la réponse d'une autre manière.
traxium
@traxium +1 pour une solution FP. Bien que ce soit morbide complexe pour quelqu'un qui débute avec JS, votre solution se trouve également être l'une des plus performantes pour résoudre le problème d'OP.
SeaWarrior404
Selon jsben.ch/ujXlk , l'autre méthode est plus rapide.
VFDan
48

Voici une autre solution, si vous utilisez ES6 en utilisant l'opérateur de propagation:

var arr = [0, 21, 22, 7];

const indexOfMaxValue = arr.indexOf(Math.max(...arr));
Lanil Marasinghe
la source
6

Sauf erreur, je dirais que c'est pour écrire votre propre fonction.

function findIndexOfGreatest(array) {
  var greatest;
  var indexOfGreatest;
  for (var i = 0; i < array.length; i++) {
    if (!greatest || array[i] > greatest) {
      greatest = array[i];
      indexOfGreatest = i;
    }
  }
  return indexOfGreatest;
}
Dan Tao
la source
6

Si vous utilisez un trait de soulignement, vous pouvez utiliser ce joli short one-liner:

_.indexOf(arr, _.max(arr))

Il trouvera d'abord la valeur du plus grand élément du tableau, dans ce cas 22. Ensuite, il retournera l'index de l'endroit où 22 se trouve dans le tableau, dans ce cas 2.

Kevin
la source
6

Une autre solution de max utilisant reduce:

[1,2,5,0,4].reduce((a,b,i) => a[0] < b ? [b,i] : a, [Number.MIN_VALUE,-1])
//[5,2]

Cela renvoie [5e-324, -1]si le tableau est vide. Si vous voulez juste l'index, mettez[1] après.

Min via (Changer en >et MAX_VALUE):

[1,2,5,0,4].reduce((a,b,i) => a[0] > b ? [b,i] : a, [Number.MAX_VALUE,-1])
//[0, 3]
Randompast
la source
1

EDIT: Il y a des années, j'ai donné une réponse à cela qui était grossière, trop précise et trop compliquée. Alors je le modifie. Je préfère les réponses fonctionnelles ci-dessus pour leur aspect soigné mais pas pour leur lisibilité; mais si j'étais plus familier avec javascript, je les aimerais peut-être aussi pour cela.

Pseudo code:

Index de suivi contenant la plus grande valeur. Supposons que l'indice 0 soit le plus grand au départ. Comparez avec l'index actuel. Mettez à jour l'index avec la valeur la plus élevée si nécessaire.

Code:

var mountains = [3, 1, 5, 9, 4];

function largestIndex(array){
  var counter = 1;
  var max = 0;

  for(counter; counter < array.length; counter++){
    if(array[max] < array[counter]){
        max = counter;
    }
  }
  return max;
}

console.log("index with largest value is: " +largestIndex(mountains));
// index with largest value is: 3
ross studtman
la source
Merci! J'ai dû m'amuser davantage.
ross studtman
1
function findIndicesOf(haystack, needle)
{
    var indices = [];

    var j = 0;
    for (var i = 0; i < haystack.length; ++i) {
        if (haystack[i] == needle)
            indices[j++] = i;
    }
    return indices;
}

passer arrayà haystacket Math.max(...array)à needle. Cela donnera tous les éléments max du tableau, et il est plus extensible (par exemple, vous devez également trouver des valeurs min)

Edward Karak
la source
1

Si vous créez une copie du tableau et le triez par ordre décroissant, le premier élément de la copie sera le plus grand. Ensuite, vous pouvez trouver son index dans le tableau d'origine.

var sorted = [...arr].sort((a,b) => b - a)
arr.indexOf(sorted[0])

La complexité en temps est O (n) pour la copie, O (n * log (n)) pour le tri et O (n) pour l'indexOf.

Si vous devez le faire plus rapidement, la réponse de Ry est O (n).

rodurico
la source
0

 var arr=[0,6,7,7,7];
 var largest=[0];
 //find the largest num;
 for(var i=0;i<arr.length;i++){
   var comp=(arr[i]-largest[0])>0;
      if(comp){
	  largest =[];
	  largest.push(arr[i]);
	  }
 }
 alert(largest )//7
 
 //find the index of 'arr'
 var arrIndex=[];
 for(var i=0;i<arr.length;i++){
    var comp=arr[i]-largest[0]==0;
	if(comp){
	arrIndex.push(i);
	}
 }
 alert(arrIndex);//[2,3,4]

mos wen
la source
-1

Une version stable de cette fonction ressemble à ceci:

// not defined for empty array
function max_index(elements) {
    var i = 1;
    var mi = 0;
    while (i < elements.length) {
        if (!(elements[i] < elements[mi]))
            mi = i;
        i += 1;
    }
    return mi;
}
Peter Stuifzand
la source
Que signifie «stable» dans ce contexte?
Ry-
Je suppose qu'il voulait dire "convenable"
Ikbel