【问题标题】:Find the min/max element of an array in JavaScript在 JavaScript 中查找数组的最小/最大元素
【发布时间】:2010-12-12 18:07:57
【问题描述】:

如何轻松获取 JavaScript 数组的最小或最大元素?

示例伪代码:

let array = [100, 0, 50]

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

【问题讨论】:

  • 注意: 使用 ECMAScript 6,您可以使用新的 spread operator(三个点:...)和 Math.max(),如下所示:Math.max(...[2, 5, 16, 1])。请参阅由MDN documentation 制成的my answer
  • 这里是最常用方法的速度比较基准:jsben.ch/#/1QuTg
  • 没有 ES6 Math.max.apply(null, [2,5,16,1])
  • @AronFiechter 你真的看过我的回答吗?我通过代码示例和基准非常详细地解释了所有选项。只有当数组的大小大于 100000 时,调用堆栈大小才会成为问题。虽然必须考虑调用堆栈,但在大多数情况下,这不是问题,更简洁的代码胜过缺点。
  • 这个调用栈可能是个问题。有一个 HackerRank 问题需要找到最小值和最大值,并且测试在 10 秒的限制下运行。 HackerRank 为第 9 到第 14 次测试传入的数组长度大于 100,000;如果使用以下答案中的 reduce 解决方案,则会失败。 for循环会通过一些

标签: javascript


【解决方案1】:

使用Math.max()Math.min()

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

以下函数使用Function.prototype.apply() 查找数值数组中的最大元素。 getMaxOfArray([1, 2, 3]) 等价于Math.max(1, 2, 3),但您可以在任何大小的程序构造数组上使用getMaxOfArray()

function getMaxOfArray(numArray) {
  return Math.max.apply(null, numArray);
}

或者使用新的扩展运算符,获取数组的最大值变得容易得多。

var arr = [1, 2, 3];
var max = Math.max(...arr); // 3
var min = Math.min(...arr); // 1

【讨论】:

    【解决方案2】:

    如果您使用原型,ChaosPandion 的解决方案可以工作。如果没有,请考虑:

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

    如果数组值不是整数,上面将返回 NaN,因此您应该构建一些功能来避免这种情况。否则这将起作用。

    【讨论】:

    • jeerose,当 Roatin Marth 只有 (null, this) 时,为什么你有 (Math, this) 作为 agruments?
    • @HankH:在对我自己的回答的评论中查看我对您的评论的回复。
    • 我不明白您所说的“如果您使用原型,ChaosPandion 的解决方案有效”是什么意思。除了使用Math 对象作为上下文之外,您的解决方案有何不同?
    • 抱歉,我的意思是如果你扩展原型,你的原型就可以工作。道歉。
    • 那么,jeerose 和 ChaosPandion 哪个更好?
    【解决方案3】:

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

    min( map , all = false ) 返回数组中的元素 最低值。 map 可以是映射要检查的值的函数,或者 用作快捷方式的字符串。如果一切都为真,将返回所有分钟 数组中的值。

    ma​​x( map , all = false ) 返回数组中的元素 最大的价值。 map 可能是映射要检查的值的函数 或用作快捷方式的字符串。如果全部为真,将返回所有最大值 数组中的值。

    例子:

    [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-Dashunderscore.js 等库也提供了类似的强大的最小值和最大值函数:

    来自 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 }
    

    【讨论】:

      【解决方案4】:
      let arr = [2,5,3,5,6,7,1];
      
      let max = Math.max(...arr); // 7
      let min = Math.min(...arr); // 1
      

      【讨论】:

      • 这个问题的其他多个回答者已经提供了这个解决方案。你的回答增加了什么?
      【解决方案5】:

      试试

      let max= a=> a.reduce((m,x)=> m>x ? m:x);
      let min= a=> a.reduce((m,x)=> m<x ? m:x);
      

      let max= a=> a.reduce((m,x)=> m>x ? m:x);
      let min= a=> a.reduce((m,x)=> m<x ? m:x);
      
      // TEST - pixel buffer
      let arr = Array(200*800*4).fill(0); 
      arr.forEach((x,i)=> arr[i]=100-i%101); 
      
      console.log('Max', max(arr));
      console.log('Min', min(arr))

      对于 Math.min/max (+apply) 我们得到错误:

      超出最大调用堆栈大小 (Chrome 74.0.3729.131)

      // TEST - pixel buffer
      let arr = Array(200*800*4).fill(0); 
      arr.forEach((x,i)=> arr[i]=100-i%101); 
      
      // Exception: Maximum call stack size exceeded
      
      try {
        let max1= Math.max(...arr);          
      } catch(e) { console.error('Math.max :', e.message) }
      
      try {
        let max2= Math.max.apply(null, arr); 
      } catch(e) { console.error('Math.max.apply :', e.message) }
      
      
      // same for min

      【讨论】:

        【解决方案6】:

        你可以使用lodash的方法

        _.max([4, 2, 8, 6]);
        returns => 8
        

        https://lodash.com/docs/4.17.15#max

        _.min([4, 2, 8, 6]);
        returns => 2
        

        https://lodash.com/docs/4.17.15#min

        【讨论】:

        • 此解决方案适用于大型阵列。不报错Maximum call stack size exceeded
        【解决方案7】:

        如果您使用的是 prototype.js 框架,那么这段代码可以正常工作:

        arr.min();
        arr.max();
        

        在此处记录:Javascript prototype framework for max

        【讨论】:

          【解决方案8】:
          minHeight = Math.min.apply({},YourArray);
          minKey    = getCertainKey(YourArray,minHeight);
          maxHeight = Math.max.apply({},YourArray);
          maxKey    = getCertainKey(YourArray,minHeight);
          function getCertainKey(array,certainValue){
             for(var key in array){
                if (array[key]==certainValue)
                   return key;
             }
          } 
          

          【讨论】:

            【解决方案9】:

            这是一个普通的 JS 方法。

            function getMinArrayVal(seq){
                var minVal = seq[0];
                for(var i = 0; i<seq.length-1; i++){
                    if(minVal < seq[i+1]){
                    continue;
                    } else {
                    minVal = seq[i+1];
                    }
                }
                return minVal;
            }
            

            【讨论】:

              【解决方案10】:

              您可以使用 Array.sort,但您必须编写一个简单的数字排序函数,因为默认是字母。

              Look at example 2 here.

              然后你可以抓住arr[0]arr[arr.length-1] 得到最小值和最大值。

              【讨论】:

              • 问题是关于最小值/最大值,而不是排序。
              • @Ates Goral - 当然,但你肯定可以理解排序列表允许 O(1) 访问最小值和最大值,是吗?
              • 性能方面,排序会进行更多的交换。这必须考虑在内。
              • 我同意排序是一种有效的简单方法;但是,@ChaosPandion 指出的性能问题是真实存在的。
              【解决方案11】:

              我喜欢Linus's reduce() approach,尤其是对于大型数组。但是只要你知道你需要最小值和最大值,为什么要遍历数组两次呢?

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

              【讨论】:

                【解决方案12】:

                创建一个简单的对象

                var myArray = new Array();
                
                myArray = [10,12,14,100];
                
                var getMaxHeight = {
                     hight : function( array ){ return Math.max.apply( Math, array );
                }
                
                getMaxHeight.hight(myArray);
                

                【讨论】:

                • 为什么你实际上需要一个对象呢?这只是您最终使用的功能。还有,你为什么要定义你的数组两次?
                • 这里的主要解决方案不是数组创建约定或为变量赋值。您可以根据需要使用创建数组并根据需要分配值。
                • 我知道这不是主要解决方案。事实上,它甚至不是解决方案的一部分。如果是的话,也许我会否决你,但我没有。我只是好奇你为什么要这样写代码。
                【解决方案13】:

                以下脚本在 ndoejs 中为我工作:

                 var numbers = [1, 2, 3, 4];
                 console.log('Value:: ' + Math.max.apply(null, numbers) ); // 4
                

                【讨论】:

                  【解决方案14】:

                  嗯,我想通过下面的方式做到这一点

                  const findMaxAndMin = (arr) => {
                    if (arr.length <= 0) return -1;
                    let min = arr[0];
                    let max = arr[0];
                    arr.forEach((n) => {
                      n > max ? (max = n) : false;
                      n < min ? (min = n) : false;
                    });
                    return [min, max];
                  };
                  

                  【讨论】:

                  • 如果您不使用输出,则没有理由使用map。考虑改用forEach
                  【解决方案15】:

                  如果您需要性能,那么这是小型阵列的最佳方式:

                  var min = 99999;
                  var max = 0;
                  for(var i = 0; i < v.length; i++)
                  {
                      if(v[i] < min)
                      {
                          min = v[i];
                      }
                      if(v[i] >= max)
                      {
                          max = v[i];
                      }
                  }
                  

                  【讨论】:

                    【解决方案16】:

                    如果你有复杂的对象,你可以使用排序......例如:如果我想要获取包含以下 objs 的 MAX/MIN 值的项目。

                    var objs= [
                    {name:"Apple",value:3},
                    {name:"Love",value:32},
                    {name:"Cheese",value:1},
                    {name:"Pork",value:77},
                    {name:"Xmas",value:99}        
                    ];
                    

                    我会做一个排序:

                    objs.sort(function(a, b){return a.value-b.value});
                    

                    然后: objs[0] 是最小值,objs[objs.length-1] 是最大值。

                    【讨论】:

                    • sort 实际上更新了数组,就像@Ben 回答中提到的那样。 OP 只是关于获取最小/最大值。
                    • 您可以复制当前数组并对其进行排序并获得最小值/最大值。几行额外的代码。但是,我只是想发布一个替代解决方案。哈哈。我正在处理的数组有 3 个级别的对象,我必须从第 2 级获取最小/最大值。这不仅仅是从单值数组中获取最小值/最大值。
                    【解决方案17】:

                    为了防止 "max" 和 "min" 在 "for ... in" 循环中列出:

                    Object.defineProperty(Array.prototype, "max", {
                        enumerable: false,
                        configurable: false,
                        writable: false,    
                        value: function() {
                            return Math.max.apply(null, this);
                        }
                    });
                    Object.defineProperty(Array.prototype, "min", {
                        enumerable: false,
                        configurable: false,
                        writable: false,    
                        value: function() {
                            return Math.min.apply(null, this);
                        }
                    });
                    

                    用法:

                    var x = [10,23,44,21,5];
                    x.max(); //44
                    x.min(); //5
                    

                    【讨论】:

                      【解决方案18】:

                      您可能不想向 Array 原型添加方法,这可能与其他库发生冲突。

                      我已经看到很多使用 forEach 的示例,我不建议将其用于大型数组,因为它与 for 循环相比性能较差。 https://coderwall.com/p/kvzbpa/don-t-use-array-foreach-use-for-instead

                      还有Math.max(Math, [1,2,3]); 总是给我NaN?

                      function minArray(a) {
                        var min=a[0]; for(var i=0,j=a.length;i<j;i++){min=a[i]<min?a[i]:min;}
                        return min;
                      }
                      
                      function maxArray(a) {
                        var max=a[0]; for(var i=0,j=a.length;i<j;i++){max=a[i]>max?a[i]:max;}
                        return max;
                      }
                      
                      minArray([1,2,3]); // returns 1
                      

                      如果你有一个对象数组,下面的 minArray() 函数示例将接受 2 个参数,第一个是数组,第二个是要比较的对象键值的键名。这种情况下的函数将返回具有最小给定键值的数组的索引。

                      function minArray(a, key) {
                        var min, i, j, index=0;
                        if(!key) {
                          min=a[0]; 
                          for(i=0,j=a.length;i<j;i++){min=a[i]<min?a[i]:min;}
                          return min;
                        }
                        min=a[0][key];
                        for(i=0,j=a.length;i<j;i++){
                          if(a[i][key]<min) {
                            min = a[i][key];
                            index = i;
                          }
                        }
                          return index;
                      }
                      
                      var a = [{fee: 9}, {fee: 2}, {fee: 5}];
                      
                      minArray(a, "fee"); // returns 1, as 1 is the proper array index for the 2nd array element.
                      

                      【讨论】:

                      • 为什么这是最佳答案?最上面的应该是stackoverflow.com/a/1669222/390014
                      • 是的,我同意使用 Math.min.apply() 来查找最小原始数组值,我记得看到 cmets 忽略了 apply 调用,这给了我空响应,这就是为什么我想出了第一个解决方案。虽然我的第二个解决方案仍然对对象数组有好处,当然除非有更好的解决方案:)
                      【解决方案19】:

                      线性的,几乎纯功能的方法

                      var min=[0, 29, 25].map((function(max) {max=-Infinity; return function(e) {return max=Math.max(max, e);}})())[0]
                      

                      更多示例:

                      找出min

                      function getMin(arr) {
                          return (ar || [0, 29, 25]).
                              map((function(max) {max=-Infinity; return function(e) {return max=Math.max(max, e);}})())[0];
                      }
                      

                      或使用Array.map 方法和变量闭包

                      function getMin(arrObjs) {
                          return (arrObjs || [{val: 0}, {val: 29}, {val: 25}]).
                              map((function(max) {max=-Infinity; return function(e) {return max=(max.val>e.val?max:e);}})())[0];
                      }
                      

                      找出最大值

                      function getMax(arr) {
                          return (ar || [0, 29, 25]).
                              map((function(v) {v=Infinity; return function(e) {return v=Math.min(v, e);}})())[0];
                      }
                      

                      对象数组

                      function getMax(arrObjs) {
                          return (arrObjs || [{val: 0}, {val: 29}, {val: 25}]).
                              map((function(v) {v=-Infinity; return function(e) {return v=(v.val<e.val?v:e);}})())[0];
                      }
                      

                      【讨论】:

                        【解决方案20】:

                        插入以逗号分隔的数字,然后单击要调用的事件,即获取最大或最小数字。

                                function maximumNumber() {
                               
                                    var numberValue = document.myForm.number.value.split(",");
                                    var numberArray = [];
                            
                                    for (var i = 0, len = numberValue.length; i < len; i += 1) {
                            
                                        numberArray.push(+numberValue[i]);
                            
                                        var largestNumber = numberArray.reduce(function (x, y) {
                                            return (x > y) ? x : y;
                                        });
                                    }
                            
                                    document.getElementById("numberOutput").value = largestNumber;
                            
                                }
                            
                                function minimumNumber() {
                          
                                    var numberValue = document.myForm.number.value.split(",");
                                    var numberArray = [];
                            
                                    for (var i = 0, len = numberValue.length; i < len; i += 1) {
                            
                                        numberArray.push(+numberValue[i]);
                            
                                        var smallestNumber = numberArray.reduce(function (x, y) {
                                            return (x < y) ? x : y;
                                        });
                                    }
                            
                                    document.getElementById("numberOutput").value = smallestNumber;
                            
                                }
                            
                            
                                    function restrictCharacters(evt) {
                            
                                        evt = (evt) ? evt : window.event;
                                        var charCode = (evt.which) ? evt.which : evt.keyCode;
                                        if (((charCode >= '48') && (charCode <= '57')) || (charCode == '44')) {
                                            return true;
                                        }
                                        else {
                                            return false;
                                        }
                                    }
                            
                            <div>    
                                    <form name="myForm">
                                    <table>
                                    <tr>
                                        <td>Insert Number</td>
                                       
                                        <td><input type="text" name="number" id="number" onkeypress="return restrictCharacters(event);" /></td>
                                        
                                        <td><input type="button" value="Maximum" onclick="maximumNumber();" /></td>
                                        
                                        <td><input type="button" value="Minimum" onclick="minimumNumber();"/></td>
                                        
                                        <td><input type="text" id="numberOutput" name="numberOutput" /></td>
                            
                                    </tr>
                                    </table>
                                    </form>
                                </div>

                        【讨论】:

                          【解决方案21】:

                          问题的递归解决方案

                          const findMinMax = (arr, max, min, i) => arr.length === i ? {
                              min,
                              max
                            } :
                            findMinMax(
                              arr,
                              arr[i] > max ? arr[i] : max,
                              arr[i] < min ? arr[i] : min,
                              ++i)
                          
                          const arr = [5, 34, 2, 1, 6, 7, 9, 3];
                          const max = findMinMax(arr, arr[0], arr[1], 0)
                          console.log(max);

                          【讨论】:

                            【解决方案22】:

                            另一种解决方案

                               let arr = [1,10,25,15,31,5,7,101];
                                let sortedArr = arr.sort((a, b) => a - b)
                            
                                let min = sortedArr[0];
                                let max = sortedArr[arr.length-1]
                            
                                console.log(`min => ${min}. Max => ${max}`)
                            

                            【讨论】:

                              【解决方案23】:

                              这里还有一个例子。使用 lodash 从数组中计算最大值/最小值。

                              let array = [100, 0, 50];
                              var func = _.over(Math.max, Math.min);
                              var [max, min] = func(...array);
                              // => [100, 0]
                              console.log(max);
                              console.log(min);
                              &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"&gt;&lt;/script&gt;

                              【讨论】:

                                【解决方案24】:

                                我设法通过这种方式解决了我的问题:

                                    var strDiv  = "4,8,5,1"
                                var arrayDivs   = strDiv.split(",")
                                var str = "";
                                
                                for (i=0;i<arrayDivs.length;i++)
                                {
                                    if (i<arrayDivs.length-1)
                                    {
                                      str = str + eval('arrayDivs['+i+']')+',';
                                    } 
                                    else if (i==arrayDivs.length-1)
                                    {
                                      str = str + eval('arrayDivs['+i+']');
                                    }
                                }
                                
                                str = 'Math.max(' + str + ')';
                                    var numMax = eval(str);
                                

                                我希望我有所帮助。

                                最好的问候。

                                【讨论】:

                                  猜你喜欢
                                  • 2013-12-15
                                  • 1970-01-01
                                  • 2014-07-21
                                  • 2021-12-25
                                  • 2020-05-08
                                  • 2017-01-17
                                  • 2018-10-17
                                  • 2015-04-18
                                  相关资源
                                  最近更新 更多