Restituisce l'indice del massimo valore in un array


139

Ho questo:

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

Qual è il modo migliore per restituire l'indice del valore più alto in un'altra variabile?


21
Non è un duplicato, leggi la domanda ... @Dancrumb Il modo in cui funziona SO è che pubblico questa domanda e per decenni a venire la gente la troverà, la leggerà e sarà grata per le informazioni che i contributori hanno pubblicato qui sotto!
Stephen,

1
@Stephen, al contrario, se leggi queste FAQ , vedrai che le domande soggettive (come quelle che iniziano "Qual è il modo migliore ...") sono espressamente scoraggiate. Tuttavia, SO è una comunità, quindi spetta alla comunità determinare se questa domanda debba essere chiusa o meno.
Dancrumb,

6
Trovare il numero più grande in un array non equivale a trovare l'indice del numero più grande in un array. Pertanto questa domanda non è un duplicato di quel riferimento pubblicato come duplicato.
Fzs2,

15
Questo NON è un duplicato - o almeno non della domanda di riferimento. Non riesco a capire i commenti negativi su questo: dire che non puoi chiedere a SO il modo migliore per fare qualcosa è ridicolo, e non è richiesto alcun esempio di codice per una domanda così concisa. In che modo il 'duplicato' referenziato ha +30 voti e questa domanda parallela MA DIVERSA, posta in uno stile molto simile, ha -3 voti? Rileggi la domanda e rimuovi i voti contrassegnati come duplicati. "indice di" è la frase chiave che devi individuare nel titolo della domanda.
pancake

@Dancrumb L'attuale consiglio in stackoverflow.com/help/dont-ask scoraggia le domande soggettive solo se ogni risposta è ugualmente valida. In questo caso, il "migliore" può essere chiaramente valutato in termini di prestazioni, terseness ed espressività.
user234461

Risposte:


165

Questo è probabilmente il modo migliore, poiché è affidabile e funziona su vecchi browser:

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

C'è anche questo one-liner:

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

Esegue il doppio del confronto necessario e genererà RangeErrorarray di grandi dimensioni. Attaccherei alla funzione.


1
Ok questa funzione restituisce il primo indice rilevato per il massimo valore. Diciamo che ho più di un indice con lo stesso valore più alto, come posso ottenere tutti questi indici?
ed1nh0,

1
@ ed1nh0: il modo più semplice è fare più passaggi. Trova il massimo con const max = arr.reduce((m, n) => Math.max(m, n)), quindi gli indici del massimo sono [...arr.keys()].filter(i => arr[i] === max).
Ry-

[...arr.keys()]genera un errore:unexpected token
ed1nh0

@ ed1nh0: quale browser / ambiente stai prendendo di mira?
Ry-

Cromo. Sto usando VueJS e immagino che il problema sia qualcosa nella configurazione del webpack.
ed1nh0

82

In una riga e probabilmente più veloce di 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"

Dove:

  • iMax- il miglior indice finora (l'indice dell'elemento max finora, sulla prima iterazione iMax = 0perché il secondo argomento reduce()è 0, non possiamo omettere il secondo argomento reduce()nel nostro caso)
  • x - l'elemento attualmente testato dall'array
  • i - l'indice attualmente testato
  • arr- il nostro array ( [0, 21, 22, 7])

Informazioni sul reduce()metodo (da "JavaScript: The Definitive Guide" di David Flanagan):

reduce () accetta due argomenti. La prima è la funzione che esegue l'operazione di riduzione. Il compito di questa funzione di riduzione è in qualche modo combinare o ridurre due valori in un singolo valore e restituire quel valore ridotto.

Le funzioni utilizzate con reduce () sono diverse dalle funzioni utilizzate con forEach () e map (). Il valore familiare, l'indice e i valori dell'array vengono passati come secondo, terzo e quarto argomento. Il primo argomento è il risultato accumulato della riduzione finora. Alla prima chiamata alla funzione, questo primo argomento è il valore iniziale passato come secondo argomento per ridurre (). Nelle chiamate successive, è il valore restituito dalla precedente chiamata della funzione.

Quando si richiama ridurre () senza alcun valore iniziale, utilizza il primo elemento dell'array come valore iniziale. Ciò significa che la prima chiamata alla funzione di riduzione avrà il primo e il secondo elemento dell'array come primo e secondo argomento.


12
@traxium Mentre la tua spiegazione è ottima, l'esempio potrebbe essere più chiaro per coloro che sono meno nella programmazione funzionale se usassimo variabili più descrittive. Di ': arr.reduce((bestIndexSoFar, currentlyTestedValue, currentlyTestedIndex, array) => currentlyTestedValue > array[bestIndexSoFar] ? currentlyTestedIndex : bestIndexSoFar, 0);, che può essere descritto come: iterate dell'array a partire dall'indice 0 (2 ° parametro), se currentlyTestedValue è superiore al valore dell'elemento al bestIndexSoFar , poi riportare il currentlyTestedIndex alla successiva iterazione come bestIndexSoFar .
niieani,

1
@traxium Risposta eccezionale. Sono anche d'accordo con @niieani Ecco un esempio reale mondo ho implementato: this.methods.reduce((methodIndex, currentMethod, currentMethodIndex, methods) => currentMethod.price <= methods[methodIndex].price ? currentMethodIndex : methodIndex, 0).
Daniel,

2
@DanielK, la risposta con i nomi dei parametri "completi" non rientrava in una riga dello stackoverflow. Apparirà una barra di scorrimento orizzontale e non sarebbe molto comodo leggere lo snippet mentre si scorre orizzontalmente. Comunque grazie per i suggerimenti. Ho modificato la risposta in un altro modo.
traxium,

@traxium +1 per una soluzione FP. Mentre è morbosamente complesso per qualcuno che ha appena iniziato con JS, la tua soluzione sembra anche essere una delle più performanti per risolvere il problema di OP.
SeaWarrior404,

Secondo jsben.ch/ujXlk , l'altro metodo è più veloce.
VFDan

47

Ecco un'altra soluzione, se si utilizza ES6 utilizzando l'operatore spread:

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

const indexOfMaxValue = arr.indexOf(Math.max(...arr));

6

A meno che non mi sbagli, direi che è scrivere la tua funzione.

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

6

Se stai utilizzando il trattino basso, puoi usare questo simpatico short one-liner:

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

Prima troverà il valore dell'elemento più grande nell'array, in questo caso 22. Quindi restituirà l'indice di dove 22 è all'interno dell'array, in questo caso 2.


6

Un'altra soluzione di max utilizzando reduce:

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

Questo ritorna [5e-324, -1]se l'array è vuoto. Se vuoi solo l'indice, metti [1]dopo.

Min via (Cambia in >e MAX_VALUE):

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

1

EDIT: anni fa ho dato una risposta a questo che era grossolano, troppo specifico e troppo complicato. Quindi lo sto modificando. Preferisco le risposte funzionali sopra per il loro fattore pulito ma non per la loro leggibilità; ma se avessi più familiarità con JavaScript, mi potrebbero piacere anche per quello.

Pseudo codice:

Traccia l'indice che contiene il valore più grande. Supponiamo che inizialmente l'indice 0 sia il più grande. Confronta con l'indice corrente. Aggiorna l'indice con il valore più grande, se necessario.

Codice:

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

Grazie! Ho dovuto rovinare ulteriormente.
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;
}

passare arrayda haystacke Math.max(...array)verso needle. Ciò fornirà tutti gli elementi massimi dell'array ed è più estensibile (ad esempio, è necessario trovare anche i valori minimi)


1

Se si crea una copia dell'array e la si ordina in ordine decrescente, il primo elemento della copia sarà il più grande. Di quanto puoi trovare il suo indice nella matrice originale.

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

La complessità temporale è O (n) per la copia, O (n * log (n)) per l'ordinamento e O (n) per indexOf.

Se devi farlo più velocemente, la risposta di Ry è O (n).


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]


-1

Una versione stabile di questa funzione è simile alla seguente:

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

Cosa significa "stabile" in questo contesto?
Ry-

Immagino che intendesse "adatto"
Ikbel

-5

Semplice

maxarr: function(){
let maxval = 0;
let maxindex = null;
for (i = 0; i < arr.length; i++){
if (arr[i] > maxval) {
maxval = arr[i];
maxindex = i;
}
}
}

Mi dispiace non ho letto chiaramente il post ora aggiornerò il codice
vidhyesh il

Spiega un po 'di più la tua risposta (aiuta a rimuovere i downvotes) e prova anche a differenziarla da un'altra risposta (ad esempio: usare meno risorse o è più veloce nel calcolo ... ecc.). (Fine della revisione della risposta di bassa qualità).
ZF007,

Questo non restituisce l' indice del valore massimo; questo restituisce solo il valore massimo positivo .
Cœur il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.