Gibt den Index des größten Werts in einem Array zurück

137

Ich habe das:

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

Wie kann der Index des höchsten Werts am besten in eine andere Variable zurückgegeben werden?

Stephen
quelle
21
Das ist kein Duplikat, lesen Sie die Frage… @Dancrumb So funktioniert SO: Ich poste diese Frage und in den kommenden Jahrzehnten werden die Leute sie finden, lesen und dankbar sein für die Informationen, die die Mitwirkenden unten gepostet haben!
Stephen
1
@Stephen, im Gegenteil, wenn Sie diese FAQ lesen, werden Sie feststellen, dass subjektive Fragen (wie diejenigen, die mit "Was ist der beste Weg ..." beginnen) ausdrücklich nicht empfohlen werden. Da SO jedoch eine Community ist, muss die Community entscheiden, ob diese Frage geschlossen werden soll oder nicht.
Dancrumb
6
Das Finden der größten Zahl in einem Array ist nicht dasselbe wie das Finden des Index der größten Zahl in einem Array. Daher ist diese Frage kein Duplikat dieser Referenz, die als Duplikat veröffentlicht wurde.
Fzs2
15
Dies ist KEIN Duplikat - oder zumindest nicht der referenzierten Frage. Ich kann die Abstimmungen dazu nicht verstehen - zu sagen, dass man SO nicht fragen kann, ist der beste Weg, etwas zu tun, lächerlich, und für eine so kurze Frage ist kein Codebeispiel erforderlich. Wie kommt es, dass das referenzierte "Duplikat" +30 Stimmen hat und diese parallele, ABER UNTERSCHIEDLICHE Frage, die in einem sehr ähnlichen Stil gestellt wird, -3 Stimmen hat? Bitte lesen Sie die Frage erneut und entfernen Sie Ihre als doppelt gekennzeichneten Stimmen. "index of" ist der Schlüsselbegriff, den Sie im Fragentitel finden müssen.
Pfannkuchen
@Dancrumb Der aktuelle Rat in stackoverflow.com/help/dont-ask rät nur dann von subjektiven Fragen ab, wenn jede Antwort gleichermaßen gültig ist. In diesem Fall kann "best" eindeutig in Bezug auf Leistung, Knappheit und Ausdruckskraft bewertet werden.
user234461

Antworten:

165

Dies ist wahrscheinlich der beste Weg, da es zuverlässig ist und mit alten Browsern funktioniert:

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

Es gibt auch diesen Einzeiler:

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

Es führt doppelt so viele Vergleiche wie nötig durch und wirft jedoch RangeErrorgroße Arrays auf. Ich würde mich an die Funktion halten.

Ry-
quelle
1
Ok, diese Funktion gibt den ersten gefundenen Index für den größten Wert zurück. Angenommen, ich habe mehr als einen Index mit demselben höchsten Wert. Wie erhalte ich all diese Indizes?
ed1nh0
1
@ ed1nh0: Der einfache Weg besteht darin, mehrere Durchgänge durchzuführen. Finden Sie das Maximum mit const max = arr.reduce((m, n) => Math.max(m, n)), dann sind die Indizes des Maximums mit [...arr.keys()].filter(i => arr[i] === max).
Ry-
[...arr.keys()]gibt einen Fehler aus:unexpected token
ed1nh0
@ ed1nh0: Auf welchen Browser / welche Umgebung zielen Sie ab?
Ry-
Chrom. Ich verwende VueJS und ich denke, das Problem liegt in der Webpack-Konfiguration.
ed1nh0
81

In einer Zeile und wahrscheinlich schneller als 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"

Wo:

  • iMax- der beste Index so weit (der Index des max - Elements so weit, auf der ersten Iteration , iMax = 0da das zweite Argument reduce()ist 0, können wir nicht das zweite Argument weglassen reduce()in unserem Fall)
  • x - das aktuell getestete Element aus dem Array
  • i - der aktuell getestete Index
  • arr- unser Array ( [0, 21, 22, 7])

Über die reduce()Methode (aus "JavaScript: The Definitive Guide" von David Flanagan):

redu () benötigt zwei Argumente. Die erste ist die Funktion, die die Reduktionsoperation ausführt. Die Aufgabe dieser Reduktionsfunktion besteht darin, zwei Werte irgendwie zu einem einzigen Wert zu kombinieren oder zu reduzieren und diesen reduzierten Wert zurückzugeben.

Mit redu () verwendete Funktionen unterscheiden sich von den mit forEach () und map () verwendeten Funktionen. Die bekannten Werte für Wert, Index und Array werden als zweites, drittes und viertes Argument übergeben. Das erste Argument ist das akkumulierte Ergebnis der bisherigen Reduzierung. Beim ersten Aufruf der Funktion ist dieses erste Argument der Anfangswert, den Sie als zweites zu reduzierendes Argument () übergeben haben. Bei nachfolgenden Aufrufen ist dies der Wert, der vom vorherigen Aufruf der Funktion zurückgegeben wurde.

Wenn Sie redu () ohne Anfangswert aufrufen, wird das erste Element des Arrays als Anfangswert verwendet. Dies bedeutet, dass der erste Aufruf der Reduktionsfunktion das erste und das zweite Array-Element als erstes und zweites Argument enthält.

Traxium
quelle
12
@traxium Obwohl Ihre Erklärung großartig ist, könnte das Beispiel für diejenigen, die sich weniger mit funktionaler Programmierung beschäftigen, klarer sein, wenn wir beschreibendere Variablen verwenden würden. Sagen arr.reduce((bestIndexSoFar, currentlyTestedValue, currentlyTestedIndex, array) => currentlyTestedValue > array[bestIndexSoFar] ? currentlyTestedIndex : bestIndexSoFar, 0);, die wie folgt beschrieben werden kann: das Array aus Iterierte Index beginnend 0 (2. Parameter), wenn currentlyTestedValue höher als der Wert des Elements an der ist bestIndexSoFar , dann die Rückkehr currentlyTestedIndex auf die nächste Iteration als bestIndexSoFar .
Niieani
1
@traxium Super Antwort. Ich stimme auch @niieani zu. Hier ist ein Beispiel aus der Praxis, das ich implementiert habe : this.methods.reduce((methodIndex, currentMethod, currentMethodIndex, methods) => currentMethod.price <= methods[methodIndex].price ? currentMethodIndex : methodIndex, 0).
Daniel
2
@ DanielK, Die Antwort mit den "vollständigen" Parameternamen würde nicht in eine Stapelüberlaufzeile passen. Es würde eine horizontale Bildlaufleiste angezeigt, und es wäre nicht sehr praktisch, das Snippet beim horizontalen Bildlauf zu lesen. Trotzdem danke für die Vorschläge. Ich habe die Antwort auf andere Weise bearbeitet.
Traxium
@traxium +1 für eine FP-Lösung. Während es für jemanden, der gerade erst mit JS anfängt, krankhaft komplex ist, ist Ihre Lösung zufällig auch eine der leistungsstärksten zur Lösung des OP-Problems.
SeaWarrior404
Laut jsben.ch/ujXlk ist die andere Methode schneller.
VFDan
45

Hier ist eine andere Lösung: Wenn Sie ES6 mit dem Spread-Operator verwenden:

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

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

Wenn ich mich nicht irre, würde ich sagen, dass es darum geht, eine eigene Funktion zu schreiben.

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
quelle
6

Wenn Sie einen Unterstrich verwenden, können Sie diesen schönen kurzen Einzeiler verwenden:

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

In diesem Fall wird zuerst der Wert des größten Elements im Array ermittelt, in diesem Fall 22. Anschließend wird der Index zurückgegeben, in dem sich 22 innerhalb des Arrays befindet, in diesem Fall 2.

Kevin
quelle
6

Eine andere Lösung von max mit reduce:

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

Dies wird zurückgegeben, [5e-324, -1]wenn das Array leer ist. Wenn Sie nur den Index möchten, setzen Sie [1]nach.

Min via (Wechsel zu >und MAX_VALUE):

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

EDIT: Vor Jahren gab ich eine Antwort darauf, die grob, zu spezifisch und zu kompliziert war. Also bearbeite ich es. Ich bevorzuge die obigen funktionalen Antworten wegen ihres ordentlichen Faktors, aber nicht wegen ihrer Lesbarkeit. aber wenn ich mit Javascript besser vertraut wäre, würde ich sie vielleicht auch dafür mögen.

Pseudocode:

Verfolgen Sie den Index, der den größten Wert enthält. Angenommen, Index 0 ist anfangs am größten. Vergleichen Sie mit dem aktuellen Index. Aktualisieren Sie gegebenenfalls den Index mit dem größten Wert.

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
quelle
Vielen Dank! Ich musste mich weiter damit anlegen.
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;
}

weitergeben arrayzu haystackund Math.max(...array)zu needle. Dies gibt alle max-Elemente des Arrays an und ist erweiterbarer (zum Beispiel müssen Sie auch min-Werte finden).

Edward Karak
quelle
1

Wenn Sie eine Kopie des Arrays erstellen und absteigend sortieren, ist das erste Element der Kopie das größte. Dann finden Sie den Index im ursprünglichen Array.

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

Die zeitliche Komplexität beträgt O (n) für die Kopie, O (n * log (n)) für die Sortierung und O (n) für den Index.

Wenn Sie es schneller machen müssen, lautet Rys Antwort O (n).

rodurico
quelle
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
quelle
-1

Eine stabile Version dieser Funktion sieht folgendermaßen aus:

// 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
quelle
Was bedeutet in diesem Zusammenhang „stabil“?
Ry-
Ich denke, er meinte "geeignet"
Ikbel
-5

Einfach

maxarr: function(){
let maxval = 0;
let maxindex = null;
for (i = 0; i < arr.length; i++){
if (arr[i] > maxval) {
maxval = arr[i];
maxindex = i;
}
}
}
Vidhyesh
quelle
Entschuldigung, ich habe den Beitrag jetzt nicht klar gelesen. Ich werde den Code aktualisieren
vidhyesh
Bitte erläutern Sie Ihre Antwort etwas weiter (hilft, die Abstimmungen zu entfernen) und versuchen Sie auch, sie von anderen Antworten zu unterscheiden (z. B. weniger Ressourcen verbrauchen oder schneller rechnen ... usw.). (Ende der Überprüfung der Antwort von geringer Qualität).
ZF007
Dies gibt nicht den Index des Maximalwerts zurück. Dies gibt nur den maximalen positiven Wert zurück.
Cœur