返回数组中最大值的索引


138

我有这个:

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

将最大值索引返回到另一个变量的最佳方法是什么?


21
那不是重复的,请阅读问题……@Dancrumb SO的工作方式是我发布此问题,几十年来,人们会找到它,阅读它,并感谢以下贡献者提供的信息!
Stephen

1
相反,@ Stephen,如果您阅读此常见问题解答,您会发现主观问题(例如以“什么是最好的方式...”开头的问题)被劝阻。但是,SO是一个社区,因此由社区来确定是否应该关闭此问题。
Dancrumb 2012年

6
在数组中查找最大数目与在数组中查找最大数目的索引不同。因此,此问题与发布为重复的参考文​​献不同。
Fzs2

15
这不是重复的内容,或者至少不是所引用问题的重复内容。我无法理解对此的不满-说您不能要求做某事的最佳方法是荒谬的,并且对于这样一个简洁的问题,不需要任何代码示例。所引用的“重复”如何获得+30票,而与此类似但又不同的并行问题却获得-3票?请重新阅读问题,并删除您的重复标记。“索引为”是您需要在问题标题中发现的关键词。
pancake 2013年

@Dancrumb 仅当每个答案都同样有效时,stackoverflow.com / help / dont-ask中的当前建议才会阻止主观问题。在这种情况下,可以从性能,简洁性和表达性方面明确评估“最佳”。
user234461 '18

Answers:


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:简单的方法是进行多次通过。用找到最大值const max = arr.reduce((m, n) => Math.max(m, n)),则最大值的索引为[...arr.keys()].filter(i => arr[i] === max)
Ry-

[...arr.keys()]输出错误:unexpected token
ed1nh0

@ ed1nh0:您定位到哪个浏览器/环境?
Ry-

铬。我正在使用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因为to的第二个参数reduce()0reduce()在本例中我们不能省略to的第二个参数)
  • x -数组中当前测试的元素
  • i -当前测试的索引
  • arr-我们的数组([0, 21, 22, 7]

关于该reduce()方法(摘自David Flanagan的“ JavaScript:权威指南”):

reduce()有两个参数。第一个是执行归约运算的功能。此归约函数的任务是以某种方式将两个值组合或归约为一个值,并返回该归约值。

与reduce()一起使用的函数不同于与forEach()和map()一起使用的函数。熟悉的值,索引和数组值作为第二,第三和第四自变量传递。第一个论点是迄今为止减少量的累计结果。在第一次调用该函数时,第一个参数是您作为reduce()的第二个参数传递的初始值。在后续调用中,它是该函数先前调用返回的值。

当您调用没有初始值的reduce()时,它将使用数组的第一个元素作为初始值。这意味着对简化函数的第一次调用将把第一和第二数组元素作为其第一和第二自变量。


12
@traxium尽管您的解释很棒,但是如果我们使用更多的描述性变量,那么对于函数编程较少的人来说,该示例可能会更清楚。说:arr.reduce((bestIndexSoFar, currentlyTestedValue, currentlyTestedIndex, array) => currentlyTestedValue > array[bestIndexSoFar] ? currentlyTestedIndex : bestIndexSoFar, 0);,其可以被描述为:迭代阵列从索引0(第2参数)开始,如果currentlyTestedValue比在所述元素的值更高bestIndexSoFar,则返回currentlyTestedIndex到下一次迭代的bestIndexSoFar
niieani

1
@traxium很棒的答案。我也同意@niieani这是一个现实世界的例子,我实现:this.methods.reduce((methodIndex, currentMethod, currentMethodIndex, methods) => currentMethod.price <= methods[methodIndex].price ? currentMethodIndex : methodIndex, 0)
丹尼尔(Daniel)

2
@DanielK,带有“完整”参数名称的答案不适合一个stackoverflow行。将会出现一个水平滚动条,并且在水平滚动时阅读代码片段不是很方便。无论如何,谢谢你的建议。我用另一种方式编辑了答案。
traxium

FP解决方案的@traxium +1。对于刚开始使用JS的人来说,它的病态复杂,而您的解决方案也恰好是解决OP问题的最有效的解决方案之一。
SeaWarrior404 '19

根据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

max使用的另一种解决方案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

编辑:几年前,我对此给出了一个答案,该答案是总的,过于具体和过于复杂的。所以我正在编辑。我赞成上面的功能性回答,因为它们整洁,但不可读。但是,如果我对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

谢谢!我不得不进一步弄乱它。
罗斯·斯图特曼

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

通过arrayhaystackMath.max(...array)needle。这将提供数组的所有最大元素,并且更具扩展性(例如,您还需要查找最小值)


1

如果创建数组的副本并将其降序排序,则副本的第一个元素将是最大的。比您可以在原始数组中找到它的索引。

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

复制的时间复杂度为O(n),排序的时间复杂度为O(n * log(n)),而indexOf的时间复杂度为O(n)。

如果您需要更快地执行此操作,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;
}

在这种情况下,“稳定”是什么意思?
Ry-

我猜他的意思是“合适”
Ikbel

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

抱歉,我现在没有清楚地阅读该帖子,我将更新代码
vidhyesh

请进一步解释您的答案(有助于消除掉票),并尝试将其与其他答案区分开(例如:使用更少的资源或计算速度更快等)。(低质量答案审阅的结尾)。
ZF007

这不会返回最大值的索引。这只是返回最大正值
心教堂
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.