Повернення індексу найбільшого значення в масиві


139

У мене це:

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

Який найкращий спосіб повернути індекс найвищого значення в іншу змінну?


21
Це не дублікат, читайте питання… @Dancrumb Як я так працюю, я публікую це питання, і люди протягом наступних десятиліть знайдуть його, прочитають його та будуть вдячні за інформацію, яку розмістили вкладники нижче!
Стівен

1
@Stephen, навпаки, якщо ви прочитаєте цей FAQ , ви побачите, що суб'єктивні запитання (наприклад, ті, які починаються з "Що найкраще ...") явно не відволікають. Однак SO - це спільнота, тому саме громада повинна визначити, чи слід це питання закрити чи ні.
Dancrumb

6
Пошук найбільшого числа в масиві - це не те саме, що пошук індексу найбільшого числа в масиві. Тому це питання не є дублікатом цієї посилання, розміщеної як дублікат.
Fzs2

15
Це НЕ дублікат - або, принаймні, не згаданого питання. Я не можу зрозуміти суть цього питання - мовляв, ви не можете просити SO, як найкращий спосіб зробити щось смішне, і для такого стислого запитання не потрібен приклад коду. Як так, що у "дубліката", на який посилається, є +30 голосів, і цей паралельний НЕ РІЗНИЙ запитання, задане в дуже подібному стилі, має -3 голоси? Будь ласка, перечитайте питання та видаліть свої позначені як повторювані голоси. "індекс" - це ключова фраза, яку потрібно помітити у назві питання.
млинець

@Dancrumb Поточна порада в stackoverflow.com/help/dont-ask відлякує суб'єктивних питань лише у тому випадку, якщо кожна відповідь однаково справедлива. У цьому випадку "найкраще" можна чітко оцінити з точки зору продуктивності, лаконічності та виразності.
користувач234461

Відповіді:


165

Це, мабуть, найкращий спосіб, оскільки це надійно і працює на старих браузерах:

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

Також є такий однопластовий:

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

Він виконує вдвічі більше порівнянь, ніж необхідно, і все-таки буде кидати RangeErrorвеликі масиви. Я б дотримувався функції.


1
Гаразд, ця функція повертає перший індекс, що має найбільше значення. Скажімо, у мене більше одного індексу з однаковим найвищим значенням, як я отримую всі ці індекси?
ed1nh0

1
@ ed1nh0: найпростіший спосіб - зробити кілька проходів. Знайдіть max з const max = arr.reduce((m, n) => Math.max(m, n)), тоді індекси max [...arr.keys()].filter(i => arr[i] === max).
Ри-

[...arr.keys()]видає помилку:unexpected token
ed1nh0

@ ed1nh0: На який браузер / середовище ви орієнтовані?
Ри-

Хром. Я використовую VueJS, і, мабуть, проблема в конфігурації webpack.
ed1nh0

82

В одному рядку і, мабуть, швидше 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"

Де:

  • iMax- найкращий покажчик індексу (індекс максимального елемента до цих пір, на першій ітерації, iMax = 0оскільки другий аргумент reduce()є 0, ми не можемо опустити другий аргумент reduce()у нашому випадку)
  • x - перевірений в даний час елемент з масиву
  • i - перевірений на даний момент індекс
  • arr- наш масив ( [0, 21, 22, 7])

Про reduce()метод (з "JavaScript: Постійний посібник" Девіда Фланагана):

Redu () бере два аргументи. Перший - це функція, яка виконує операцію зменшення. Завдання цієї функції скорочення полягає в тому, щоб якось об'єднати або зменшити два значення в одне значення і повернути це зменшене значення.

Функції, які використовуються для зменшення (), відрізняються від функцій, які використовуються для forEach () та map (). Знайоме значення, значення індексу та масиву передаються як другий, третій та четвертий аргументи. Перший аргумент - це накопичений до цього часу результат скорочення. Під час першого виклику функції цей перший аргумент є початковим значенням, яке ви передали як другий аргумент для зменшення (). При наступних викликах це значення, повернене попереднім викликом функції.

Коли ви викликаєте Redu () без початкового значення, він використовує перший елемент масиву як початкове значення. Це означає, що перший виклик функції зменшення матиме перший та другий елементи масиву як перший та другий аргументи.


12
@traxium Хоча ваше пояснення чудове, приклад може бути зрозумілішим для тих, хто менше не функціонально програмує, якби ми використовували більш описові змінні. Скажи: arr.reduce((bestIndexSoFar, currentlyTestedValue, currentlyTestedIndex, array) => currentlyTestedValue > array[bestIndexSoFar] ? currentlyTestedIndex : bestIndexSoFar, 0);, яка може бути описана як: ітерація масив , починаючи з індексу 0 (2 - й параметр), якщо currentlyTestedValue вище , ніж значення елемента в bestIndexSoFar , а потім повернути currentlyTestedIndex до наступної ітерації в якості bestIndexSoFar .
niieani

1
@traxium Awesome відповідь. Я також згоден з @niieani Ось реальний приклад я реалізував: this.methods.reduce((methodIndex, currentMethod, currentMethodIndex, methods) => currentMethod.price <= methods[methodIndex].price ? currentMethodIndex : methodIndex, 0).
Даніель

2
@DanielK, Відповідь із "повними" іменами параметрів не вміститься в одному рядку stackoverflow. З'явиться горизонтальна смуга прокрутки, і було б не дуже зручно читати фрагмент під час горизонтальної прокрутки. У будь-якому випадку дякую за пропозиції. Я відредагував відповідь по-іншому.
traxium

@traxium +1 для FP-рішення. Хоча його хворобливо складний для когось, що тільки починається з JS, ваше рішення також є одним з найефективніших для вирішення проблеми ОП.
SeaWarrior404

На думку jsben.ch/ujXlk , інший метод швидший.
VFDan

47

Ось ще одне рішення: Якщо ви використовуєте ES6 за допомогою оператора спред:

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

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

6

Якщо я не помиляюся, я б сказав, що це написати власну функцію.

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

Якщо ви використовуєте підкреслення, ви можете скористатись цим приємним коротким вкладишем:

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

Він спочатку знайде значення найбільшого елемента в масиві, в цьому випадку 22. Потім він поверне індекс, де 22 знаходиться в масиві, в цьому випадку 2.


6

Ще одне рішення максу з використанням reduce:

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

Це повертається, [5e-324, -1]якщо масив порожній. Якщо ви хочете просто індекс, поставте [1]після.

Мінімум через (Змінити >та 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: Роки тому я дав відповідь на це, що було грубим, занадто конкретним і занадто складним. Тому я її редагую. Я віддаю перевагу функціональним відповідям вище за їх акуратний фактор, але не їх читабельність; але якби я був більш знайомий з JavaScript, то, можливо, вони мені також сподобаються за це.

Псевдокод:

Індекс треку, який містить найбільше значення. Припустимо, індекс 0 є найбільшим спочатку. Порівняйте з поточним індексом. Оновіть індекс з найбільшим значенням, якщо необхідно.

Код:

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

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

перейти arrayдо haystackі Math.max(...array)до needle. Це дасть усі максимальні елементи масиву, і він буде більш розширюваним (наприклад, вам також потрібно знайти мінімальні значення)


1

Якщо ви створите копію масиву і сортуєте її у порядку зменшення, перший елемент копії буде найбільшим. Тоді ви можете знайти його індекс у вихідному масиві.

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

Часова складність становить O (n) для копії, O (n * log (n)) для сортування та O (n) для indexOf.

Якщо вам потрібно зробити це швидше, відповідь 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

Стабільна версія цієї функції виглядає так:

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

Що означає «стабільний» у цьому контексті?
Ри-

Я здогадуюсь, він мав на увазі "підходящий"
Ікбель

-5

Простий

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

Вибачте, я не прочитав публікацію чітко зараз, я
оновлю

будь-ласка, поясніть свою відповідь трохи далі (допомагає видалити голоси), а також спробуйте відрізнити її від іншої відповіді (наприклад, використання менших ресурсів або швидше в обчисленні ... тощо). (Закінчення огляду відповідей низької якості).
ZF007

Це не повертає індекс максимального значення; це просто повертає максимальне додатне значення.
Cœur
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.