【问题标题】:Using reduce() to find min and max values?Javascript:使用 reduce() 查找最小值和最大值?
【发布时间】:2017-09-20 10:27:17
【问题描述】:

我有一个类的代码,我应该使用 reduce() 方法来查找数组中的最小值和最大值。但是,我们只需要使用一次调用来减少。返回数组的大小应该为 2,但我知道 reduce() 方法总是返回大小为 1 的数组。我可以使用下面的代码获得最小值,但是我不知道如何获得在同一个调用中的最大值。我假设一旦获得最大值,我就在 reduce() 方法完成后将其推送到数组中。

/**
 * Takes an array of numbers and returns an array of size 2,
 * where the first element is the smallest element in items,
 * and the second element is the largest element in items.
 *
 * Must do this by using a single call to reduce.
 *
 * For example, minMax([4, 1, 2, 7, 6]) returns [1, 7]
 */
function minMax(items) {
     var minMaxArray = items.reduce(
        (accumulator, currentValue) => {
             return (accumulator < currentValue ? accumulator : currentValue);
        }
    );

     return minMaxArray;
 }

【问题讨论】:

  • 您似乎忘了实际提出问题。请查看How to Ask。
  • but I know that the reduce() method always returns an array of size 1 - 这是不正确的。此外,reduce 只是一种通过回调迭代数组的方法,请考虑在 minMax 方法中可以在迭代器中使用的范围内的其他变量。提示:根据您的描述,您根本不必使用reduce 的返回值。
  • 阅读reduce() docs并更改accumulator的initValue

标签: javascript arrays reduce


【解决方案1】:

这里是reduce vs Array的例子

const result = Array(-10,1,2,3,4,5,6,7,8,9).reduce((a,b)=>{ return (a<b) ? a : b })

您可能希望使用相同的方法来获取字符串长度

 const result = Array("ere","reeae","j","Mukono Municipality","Sexy in the City and also").reduce((a,b)=>{ return (a.length<b.length) ? a : b })

【讨论】:

    【解决方案2】:

    我们可以通过声明一个空数组作为 reduce 函数的累加器值来实现这一点,然后在 reduce 方法的最后一次迭代中执行一组不同的操作。我们通过将所有四个参数传递给 reduce 方法(总计、项目、索引、数组)并使用索引与数组长度的比较来在最后一次迭代中做一些不同的事情来做到这一点。

    var prices = [32.99, 21.99, 6.99, 4.99, 12.99, 8.98, 5.99];
    
    var highLowPrices = prices.reduce(function(accumulatorArray, price, index, pricesArray){
        if (index === pricesArray.length-1){
            accumulatorArray.push(price);
            var returnArray = [];
            accumulatorArray.sort(function(price1, price2){
                return price1 - price2;
            });
            var lowestPrice = accumulatorArray[0];
            var highestPrice = accumulatorArray[accumulatorArray.length-1];
            returnArray.push(lowestPrice);
            returnArray.push(highestPrice);
            return returnArray;
        } else {
            accumulatorArray.push(price);
            return accumulatorArray;
        }
    }, []);
    
    console.log(highLowPrices);
    

    我故意使用了一些不必要的步骤,并使用语义上冗长的变量名来使逻辑更清晰。

    if (index === pricesArray.length-1) 表示在reduce 方法通过prices 数组的最后一次迭代中,发生了一组不同的操作。到目前为止,我们只是重新创建了价格数组,这是微不足道的。但是在最后一次迭代中,在完全重新创建了价格数组之后,我们做了一些不同的事情。我们创建另一个空数组,即我们打算返回的数组。然后我们对“accumulatorArray”变量进行排序——这是重新创建的价格数组,将其从最低到最高排序。我们现在取最低价和最高价并将它们存储在变量中。将数组按升序排序后,我们知道最低的在索引 0 处,最高的在索引 array.length - 1 处。然后我们将这些变量推送到我们之前声明的返回数组中。而不是返回累加器变量本身,我们返回我们自己特别声明的返回数组。结果是一个价格最低然后价格最高的数组。

    【讨论】:

      【解决方案3】:

      1。仅使用Math.min 和Math.max 的解决方案:

      ⚠️ 如果您使用大数组,这将不起作用,即为 Math.min() 提供许多参数,因为 "您有超过 JavaScript 引擎的参数长度限制的风险。应用函数的后果太多的参数(想想数以万计的参数)因引擎而异(JavaScriptCore 的硬编码参数限制为 65536),因为未指定限制(实际上甚至是任何过大堆栈行为的性质)。一些引擎会抛出异常。” from MDN web docs.

      function minMax(items) {
        return [
            Math.min.apply(null, items),
            Math.max.apply(null, items)
        ]
      }
      

      ...或者如果您更喜欢ES6's Spread syntax:

      const minMax = items => [
        Math.min(...items),
        Math.max(...items)
      ]
      

      2。使用Array.prototype.reduce、Math.min 和Math.max 的解决方案

      function minMax(arr) {
        return arr.reduce(function(acc, cur) {
          return [
            Math.min(cur, acc[0]),
            Math.max(cur, acc[1])
          ]
        }, [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]);
      }
      

      ...或缩短:

      const minMax = items =>
        items.reduce((acc, cur) =>
          [Math.min(cur, acc[0]), Math.max(cur, acc[1])],
          [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY]
        )
      
      

      3。包括合理验证的解决方案

      function minMax(items) {
        let newItems = []
        const isArray = Array.isArray(items)
        const onlyHasNumbers = !items.some(i => isNaN(parseFloat(i)))
      
        // only proceed if items is a non-empty array of numbers
        if (isArray && items.length > 0 && onlyHasNumbers) {
          newItems = items.reduce((acc, cur) => [
              Math.min(cur, acc[0]),
              Math.max(cur, acc[1])
            ], [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY])
        }
      
        return newItems
      }
      

      Math.min 的文档

      Math.max 的文档

      Array.prototype.reduce() 的文档

      【讨论】:

        【解决方案4】:

        你可以像这样使用。可以有任意数量的参数。

        function minValue(...args) {
            const min = args.reduce((acc, val) => {
                return acc < val ? acc : val;
            });
            return min;
        }
        
        function maxValue(...args) {
            const max= args.reduce((acc, val) => {
                return acc > val ? acc : val;
            });
            return max;
        }
        

        【讨论】:

        • 这是正确的解决方案。我不明白为什么每个人都在使用Math 的函数,而显然它们不是必需的。
        【解决方案5】:

        使用reduce函数获取数组的最小值和最大值

        const ArrayList = [1, 2, 3, 4, 3, 20, 0];
        const LargestNum = ArrayList.reduce((prev, curr) => {
              return Math.max(prev, curr)
        });
        const MinNum = ArrayList.reduce((prev,curr)=>{
              return Math.min(prev,curr)
        });
        console.log(LargestNum);
        console.log(MinNum);
        

        【讨论】:

        • 在您的示例中,它之所以有效,只是因为数组的最新值为20 和0,并且是最后一个比较的值。只需尝试将最小值和最大值放在数组的开头,我们将查看您的代码是否仍在工作:)
        • 在数组开头放置 0,20 后仍然可以正常工作,输出为 20,0
        • 好吧,我看你的答案太快了,再看一遍,似乎是正确的。我的道歉
        【解决方案6】:

        let arr = [8978, 'lol', -78, 989, NaN, null, undefined, 6, 9, 55, 989];
        
        
        let minMax = arr.reduce(([min, max], v) => [
                        Math.min(min, v) || min,
                        Math.max(max, v) || max], [Infinity, -Infinity]);
        
        
        console.log(minMax);

        它是如何工作的:

        1. || min 检查是v 号码。

        2. [Infinity, -Infinity]是.reduce初始值

        3. 它使用js destructuring赋值

        【讨论】:

        • 欢迎来到 Stack Overflow!请解释你的答案。不要只写代码。 如需帮助,请查看“How to answer”
        【解决方案7】:
        const values = [1,2,3,4,5];
        const [first] = values;
        const maxValue = values.reduce((acc, value) => Math.max(acc, value), first);
        

        【讨论】:

        • 请在您的代码中添加一些解释,以便其他人可以从中学习
        【解决方案8】:

        我知道这已经得到回答,但我离开了@Sergey Zhukov 的回答(这似乎不完整)并且能够在 2 行中获得最小值和最大值:

        let vals = [ numeric values ]
        let min = Math.min.apply(undefined, vals) 
        let max = Math.max.apply(undefined, vals)
        

        我确实看到了 Array.reduce 的价值,但是对于这样一个超级简单的用例,并且只要您了解 Function.apply 的作用,这将是我的 goto 解决方案。 p>

        【讨论】:

          【解决方案9】:

          诀窍在于提供一个空数组作为初始值参数

          arr.reduce(callback, [initialValue])
          

          initialValue [可选] 用作第一个参数的值 回调的第一次调用。如果没有提供初始值,则第一个 将使用数组中的元素。

          所以代码应该是这样的:

          function minMax(items) {
              return items.reduce((acc, val) => {
                  acc[0] = ( acc[0] === undefined || val < acc[0] ) ? val : acc[0]
                  acc[1] = ( acc[1] === undefined || val > acc[1] ) ? val : acc[1]
                  return acc;
              }, []);
          }
          

          【讨论】:

          • 这个答案的优点是适用于任意有序类型(例如字符串),而不仅仅是数字,这是一个很好的概括。一种可能的优化是将initialValue 设为[items[0], items[0]],这样您就可以避免特殊的大小写undefined,从而简化每次调用if (val &lt; acc[0]) acc[0] = val; 和if (val &gt; acc[1]) acc[1] = val; 时的最小/最大值计算
          【解决方案10】:

          在 ES6 中,您可以使用扩展运算符。一串解决方案:

           Math.min(...items)
          

          【讨论】:

          • 正在询问最小值和最大值。
          • 不错。我不知道你可以像这样使用 Math.min。我一直在做 Math.min(a,b) 而已。
          • 这会因大数组而崩溃
          • 详细说明@JimmyKane 的答案,如果您使用大数组,即为Math.min() 提供许多参数:>“您将面临超出 JavaScript 引擎参数长度限制的风险。应用具有太多参数的函数(考虑超过数万个参数)因引擎而异(JavaScriptCore 的硬编码参数限制为 65536),..." developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
          【解决方案11】:

          由于根本不需要 reduce 调用,您可以从中获得一些乐趣

          let items = [62, 3, 7, 9, 33, 6, 322, 67, 853];
          
          let arr = items.reduce((w,o,r,k,s=Math)=>[s.min.apply(0, k),s.max.apply(0, k)],[]);
          
          console.log(arr);

          你真正需要的是let minMaxArray = [Math.min.apply(0,items), Math.max.apply(0,items)]

          【讨论】:

            【解决方案12】:

            你可以使用数组作为返回值:

            function minMax(items) {
                return items.reduce(
                    (accumulator, currentValue) => {
                        return [
                            Math.min(currentValue, accumulator[0]), 
                            Math.max(currentValue, accumulator[1])
                        ];
                    }, [Number.MAX_VALUE, Number.MIN_VALUE]
                );
            }
            

            【讨论】:

            • +1,但 MIN_VALUE 令人困惑地是最小的 正 值 (>0)。你最好使用Number.INFINITY和Number.NEGATIVE_INFINITY
            • @Bergi 我想你的意思是Number.POSITIVE_INFINITY...没有Number.INFINITY。
            【解决方案13】:

            使用Math.min()和Math.max()函数的解决方案:

            function minMax(items) {
                var minMaxArray = items.reduce(function (r, n) {
                        r[0] = (!r[0])? n : Math.min(r[0], n);
                        r[1] = (!r[1])? n : Math.max(r[1], n);
                        return r;
                    }, []);
            
                return minMaxArray;
            }
            
            console.log(minMax([4, 1, 2, 7, 6]));

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-09-16
              • 2017-04-20
              • 1970-01-01
              • 2018-09-21
              • 2019-02-25
              • 2021-01-24
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多