我怎样才能轻松地获得一个JavaScript数组的最小或最大元素?

伪代码示例:

let array = [100, 0, 50]

array.min() //=> 0
array.max() //=> 100

当前回答

当意图是调用带有参数值列表的变进函数时,.apply经常被使用。

的数学。Max ([value1[,value2,…]])函数返回零个或多个数字中最大的一个。

Math.max(10, 20); // 20
Math.max(-10, -20); // -10
Math.max(-10, 20); // 20

Math.max()方法不允许传入数组。如果你有一个需要获取最大值的值列表,你通常会使用function .prototype.apply()调用这个函数,例如:

Math.max.apply(null, [10, 20]); // 20
Math.max.apply(null, [-10, -20]); // -10
Math.max.apply(null, [-10, 20]); // 20

然而,从ECMAScript 6开始,你可以使用扩展操作符:

展开运算符允许在需要多个参数(用于函数调用)或多个元素(用于数组字面量)的地方展开表达式。

使用展开运算符,上面的代码可以重写为:

Math.max(...[10, 20]); // 20
Math.max(...[-10, -20]); // -10
Math.max(...[-10, 20]); // 20

当使用可变值操作符调用函数时,您甚至可以添加额外的值,例如:

Math.max(...[10, 20], 50); // 50
Math.max(...[-10, -20], 50); // 50

奖金:

展开运算符使您能够在ES5中需要返回到命令式代码(使用push、splice等组合)的情况下使用数组文字语法创建新数组。

let foo = ['b', 'c'];
let bar = ['a', ...foo, 'd', 'e']; // ['a', 'b', 'c', 'd', 'e']

其他回答

对于大数组(~10⁷elements), Math。min和数学。max在node.js中产生RangeError(超过最大调用堆栈大小)。

对于大数组,一个快速而肮脏的解决方案是:

Array.prototype.min = function() {
    var r = this[0];
    this.forEach(function(v,i,a){if (v<r) r=v;});
    return r;
};

如果你使用sugar.js库,你可以按照你的建议编写arr.min()和arr.max()。您还可以从非数值数组中获得最小值和最大值。

min(map, all = false)返回数组中包含 最小值。Map可以是映射要检查的值的函数或 作为快捷键的字符串。如果全部为真,将返回所有的min 数组中的值。 max(map, all = false)返回数组中带有 最大的价值。Map可以是映射要检查的值的函数 或者是作为快捷键的字符串。如果all为true,将返回all max 数组中的值。

例子:

[1,2,3].min() == 1
['fee','fo','fum'].min('length') == "fo"
['fee','fo','fum'].min('length', true) == ["fo"]
['fee','fo','fum'].min(function(n) { return n.length; }); == "fo"
[{a:3,a:2}].min(function(n) { return n['a']; }) == {"a":2}
['fee','fo','fum'].max('length', true) == ["fee","fum"]

像Lo-Dash和underscore.js这样的库也提供了类似强大的min和max函数:

例子来自《Lo-Dash》:

_.max([4, 2, 8, 6]) == 8
var characters = [
  { 'name': 'barney', 'age': 36 },
  { 'name': 'fred',   'age': 40 }
];
_.max(characters, function(chr) { return chr.age; }) == { 'name': 'fred', 'age': 40 }

这里有很多不错的答案,下面是一个typescript版本,可以处理一些值未定义的列表。

如何使用:

const testDates = [
  undefined,
  new Date('July 30, 1986'),
  new Date('July 31, 1986'),
  new Date('August 1, 1986'),
]
const max: Date|undefined = arrayMax(testDates); // Fri Aug 01 1986
const min: Date|undefined = arrayMin(testDates); // Min: Wed Jul 30 1986
const test: Date = arrayMin(testDates); // Static type error
const anotherTest: undefined = arrayMin(testDates); // Static type error

定义(notEmpty定义来自这篇文章):

function arrayMax<T>(values?: (T | null | undefined)[]): T | undefined {
    const nonEmptyValues = filterEmpty(values);
    if (nonEmptyValues.length === 0) {
        return undefined;
    }
    return nonEmptyValues.reduce((a, b) => (a >= b ? a : b), nonEmptyValues[0]);
}

function arrayMin<T>(values?: (T | null | undefined)[]): T | undefined {
    const nonEmptyValues = filterEmpty(values);
    if (nonEmptyValues.length === 0) {
        return undefined;
    }
    return nonEmptyValues.reduce((a, b) => (a <= b ? a : b), nonEmptyValues[0]);
}

function filterEmpty<T>(values?: (T | null | undefined)[] | null): T[] {
    return values?.filter(notEmpty) ?? [];
}

function notEmpty<T>(value: T | null | undefined): value is T {
    if (value === null || value === undefined) return false;
    const testDummy: T = value;
    return true;
}

我没有使用数学。max函数,正如文档中建议的那样,因为这样我就可以将这个函数与任何可比对象一起使用(如果你知道如何键入它,请告诉我,这样我就可以更好地定义T)。

这也许适合你的目的。

Array.prototype.min = function(comparer) {

    if (this.length === 0) return null;
    if (this.length === 1) return this[0];

    comparer = (comparer || Math.min);

    var v = this[0];
    for (var i = 1; i < this.length; i++) {
        v = comparer(this[i], v);    
    }

    return v;
}

Array.prototype.max = function(comparer) {

    if (this.length === 0) return null;
    if (this.length === 1) return this[0];

    comparer = (comparer || Math.max);

    var v = this[0];
    for (var i = 1; i < this.length; i++) {
        v = comparer(this[i], v);    
    }

    return v;
}

我喜欢Linus的reduce()方法,特别是对于大型数组。但只要你知道你需要最小值和最大值,为什么要迭代数组两次呢?

Array.prototype.minmax = function () {
  return this.reduce(function (p, v) {
    return [(p[0] < v ? p[0] : v), (p[1] > v ? p[1] : v)];
  }, [this[0], this[0]]);
}

当然,如果你更喜欢迭代方法,你也可以这样做:

Array.prototype.minmax = function () {
    var mn = this[0], mx = this[0];
    this.forEach(function (v) {
        if (v < mn) mn = v;
        if (v > mx) mx = v;
    });
    return [mn, mx];
};