在Javascript中如何从数组中获取最小值?

121

数组justPrices包含以下值:

[0] = 1.5
[1] = 4.5
[2] = 9.9.

如何返回数组中的最小值?


3
或许这个链接可以帮到你。 - Dimitar Dimitrov
3
@DimitarDimitrov:我认为你的兄弟回答得很好。 - qwertymk
19个回答

237

在IT技术中,查找最小值的最简洁表达式可能是使用rest parameters

const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
const min = Math.min(...arr)
console.log(min)

剩余参数本质上是当您不需要更改函数上下文时Function.prototype.apply的方便缩写:


var arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
var min = Math.min.apply(Math, arr)
console.log(min)

这也是使用 Array.prototype.reduce 的一个很好的用例:

const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
const min = arr.reduce((a, b) => Math.min(a, b))
console.log(min)

虽然可能会诱人直接将Math.min传递给reduce,但回调函数还会接收其他参数:

callback (accumulator, currentValue, currentIndex, array)

在这种情况下可能会有点啰嗦。reduce 在你想要将一组复杂数据聚合成单个值时特别有用:

const arr = [{name: 'Location 1', distance: 14}, {name: 'Location 2', distance: 58}, {name: 'Location 3', distance: 20}, {name: 'Location 4', distance: 77}, {name: 'Location 5', distance: 66}, {name: 'Location 6', distance: 82}, {name: 'Location 7', distance: 42}, {name: 'Location 8', distance: 67}, {name: 'Location 9', distance: 42}, {name: 'Location 10', distance: 4}]
const closest = arr.reduce(
  (acc, loc) =>
    acc.distance < loc.distance
      ? acc
      : loc
)
console.log(closest)


当然,您始终可以使用经典迭代:

var arr,
  i,
  l,
  min

arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
min = Number.POSITIVE_INFINITY
for (i = 0, l = arr.length; i < l; i++) {
  min = Math.min(min, arr[i])
}
console.log(min)

...但即使是传统的迭代方式也可以现代化:

const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
let min = Number.POSITIVE_INFINITY
for (const value of arr) {
  min = Math.min(min, value)
}
console.log(min)


3
这个答案中的解释部分(不是代码)有些令人困惑/不正确。声称“Rest参数本质上是Function.prototype.apply的便捷简写”应该替换为:解构赋值语法(...arr)是一个JavaScript表达式,它可以将数组(或对象属性)中的值解包到各自的变量中。所以,Math.min(...arr)是一种解构赋值,它将数组展开成各自的变量。 - WebDevBooster

130

Jon Resig在这篇文章中举例说明如何通过扩展Array原型并调用底层的Math.min方法来实现,但不幸的是该方法不能接受数组作为参数,而是需要变量数量的参数。

Array.min = function( array ){
    return Math.min.apply( Math, array );
};

然后:

var minimum = Array.min(array);

2
你不推荐原型设计的原因是什么? - Marek Sebera
3
@MarekSebera,我并没有写这篇文章,我只是提供了链接。为什么不去问约翰·雷西格呢? - Darin Dimitrov
1
@MarekSebera,虽然我喜欢自己扩展Array.prototype,但我建议小心操作。 for ... in循环除了可以获取数字索引之外,还可以获取函数,如果开发人员不小心操作,很容易破坏代码。 - zzzzBov
7
Math.min 是 O(N),而 sort 是 O(N log N)。虽然 Math.min 看起来很简单,但在处理大数组时,它比 sort 慢得多。 - chuckj
2
@Davsket,Array.prototype.sort会通过更改所有索引来影响原始数组对象,而有效的Array.prototype.min函数不会产生这样的副作用。 - zzzzBov
显示剩余2条评论

52
我发现返回数组中最小值的最简单方法是在Math.min()函数上使用展开运算符。
return Math.min(...justPrices);
//returns 1.5 on example given 

通过MDN网站上的页面,您可以更好地理解它:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min

额外提示: 此方法也适用于Math.max()函数。

返回 Math.max(...justPrices); // 在给定的示例中返回 9.9。

希望这有所帮助!


2
最佳答案在这里! - Spets

13

更新:请使用Darin的/ John Resig的答案,只需记住对于min,您不需要指定thisArg,因此Math.min.apply(null, arr)将完美运行。


或者您可以对数组进行排序并获取值#1:[2,6,7,4,1].sort()[0]

[!] 但是,如果不提供自定义数字排序函数,则这仅适用于一种非常有限的情况:小于10的正数。 看看它会如何中断:

var a = ['', -0.1, -2, -Infinity, Infinity, 0, 0.01, 2, 2.0, 2.01, 11, 1, 1e-10, NaN];

// correct: 
a.sort( function (a,b) { return a === b ? 0 : a < b ? -1: 1} );
//Array [NaN, -Infinity, -2, -0.1, 0, "", 1e-10, 0.01, 1, 2, 2, 2.01, 11, Infinity]

// incorrect:
a.sort();
//Array ["", -0.1, -2, -Infinity, 0, 0.01, 1, 11, 1e-10, 2, 2, 2.01, Infinity, NaN]

而且,数组是原地修改的,这可能不是你想要的。


1
如果您想保留数组对象,则返回[2,6,7,4,1].sort()[0]。 - Davsket
"小于10的正数" - 为什么?它默认使用字符串比较吗? - Stefan Monov

12

想象一下你有这个数组:

var arr = [1, 2, 3];

ES6的方式:

var min = Math.min(...arr); //min=1

ES5方法:

var min = Math.min.apply(null, arr); //min=1
如果您正在使用D3.js,有一个方便的函数可以做到同样的效果,但会忽略undefined值并检查自然顺序:
  

d3.max(array[, accessor])

  

使用自然顺序返回给定数组中的最大值。如果数组为空,则返回undefined。可以指定可选的访问器函数,它等效于在计算最大值之前调用array.map(accessor)。

  

与内置的Math.max不同,此方法忽略未定义的值;这对于忽略缺失数据很有用。此外,元素使用自然顺序而不是数值顺序进行比较。例如,字符串["20","3"]的最大值为"3",而数字[20, 3]的最大值为20。

以下是D3 v4的源代码:

export default function(values, valueof) {
  var n = values.length,
      i = -1,
      value,
      max;

  if (valueof == null) {
    while (++i < n) { // Find the first comparable value.
      if ((value = values[i]) != null && value >= value) {
        max = value;
        while (++i < n) { // Compare the remaining values.
          if ((value = values[i]) != null && value > max) {
            max = value;
          }
        }
      }
    }
  }

  else {
    while (++i < n) { // Find the first comparable value.
      if ((value = valueof(values[i], i, values)) != null && value >= value) {
        max = value;
        while (++i < n) { // Compare the remaining values.
          if ((value = valueof(values[i], i, values)) != null && value > max) {
            max = value;
          }
        }
      }
    }
  }

  return max;
}

9

ES6是未来的发展方向。

arr.reduce((a, b) => Math.min(a, b));

我喜欢这种形式,因为它很容易推广到其他用途。


准确无误... 答案是针对最小值而非最大值的 ;) - Sten Muchow
1
也许问题是错误的,应该是对于最大值...已经有两次回答并且两次都是关于最大值...只是说一下 ¯_(ツ)_/¯。 - Mark Carpenter Jr

5
var array =[2,3,1,9,8];
var minvalue = array[0]; 
for (var i = 0; i < array.length; i++) {
    if(array[i]<minvalue)
    {
        minvalue = array[i];
    }

}
  console.log(minvalue);

3
也许有更简单的方法?
假设justPrices的值混乱无序,你不知道最小值在哪里。
justPrices[0] = 4.5
justPrices[1] = 9.9
justPrices[2] = 1.5

使用sort函数。

justPrices.sort();

它将为您排序(也可以按字母顺序),数组将以升序排列。
justPrices[0] = 1.5
justPrices[1] = 4.5
justPrices[2] = 9.9

您可以轻松地通过第一个索引获取。
justPrices[0]

我认为这比上面提出的更有用,因为如果你需要最低的3个数字作为例子呢?你也可以改变它们排列的顺序,更多信息请参见http://www.w3schools.com/jsref/jsref_sort.asp


非常聪明的解决方案! - jacktrade

1

我认为我有一个易于理解的解决方案,只使用javaScript的基础知识。

function myFunction() {
            var i = 0;
            var smallestNumber = justPrices[0];
            for(i = 0; i < justPrices.length; i++) {
                if(justPrices[i] < smallestNumber) {
                    smallestNumber = justPrices[i];
                }
            }
            return smallestNumber;
        }

变量smallestNumber被设置为justPrices的第一个元素,for循环遍历数组(假设您已经知道如何使用for循环;如果不知道,请查找)。如果数组的元素小于当前的smallestNumber(最初是第一个元素),它将替换其值。当整个数组通过循环时,smallestNumber将包含数组中最小的数字。

1

function smallest(){
  if(arguments[0] instanceof Array)
    arguments = arguments[0];

  return Math.min.apply( Math, arguments );
}
function largest(){
  if(arguments[0] instanceof Array)
    arguments = arguments[0];

  return Math.max.apply( Math, arguments );
}
var min = smallest(10, 11, 12, 13);
var max = largest([10, 11, 12, 13]);

console.log("Smallest: "+ min +", Largest: "+ max);


好奇问一下,这样做的好处是什么,与直接调用 Math.min 相比? - jiggzson
@jiggzson 请查看Darin Dimitrov的描述:“Math.min方法不幸地不接受数组,而是接受可变数量的参数”。这个解决方案适用于数组和可变数量的参数。 - Libu Mathew
我指的是你之前的例子。我注意到你进行了编辑以检测数组。我想那应该是你最初的意图。谢谢。 - jiggzson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接