【问题标题】:Finding the max value of an attribute in an array of objects在对象数组中查找属性的最大值
【发布时间】:2022-07-08 02:00:12
【问题描述】:

我正在寻找一种非常快速、干净和有效的方法来获取以下 JSON 切片中的最大 \"y\" 值:

[
  {
    \"x\": \"8/11/2009\",
    \"y\": 0.026572007
  },
  {
    \"x\": \"8/12/2009\",
    \"y\": 0.025057454
  },
  {
    \"x\": \"8/13/2009\",
    \"y\": 0.024530916
  },
  {
    \"x\": \"8/14/2009\",
    \"y\": 0.031004457
  }
]

for循环是解决它的唯一方法吗?我热衷于以某种方式使用Math.max

标签: javascript json


【解决方案1】:

要查找array 中对象的最大y 值:

    Math.max.apply(Math, array.map(function(o) { return o.y; }))

或者在更现代的 JavaScript 中:

    Math.max(...array.map(o => o.y))

【讨论】:

  • 您能否扩展此答案以显示如何返回找到最大值的对象?这将非常有帮助,谢谢!
  • 这是小提琴!希望这对某人有帮助jsfiddle.net/45c5r246
  • @MikeLyons 如果您仍然关心获取实际对象:jsfiddle.net/45c5r246/34
  • FWIW 我的理解是,当您在函数上调用 apply 时,它会使用 this 的指定值和一系列指定为数组的参数来执行函数。诀窍是 apply 将数组转换为一系列实际的函数参数。所以在这种情况下,它最终调用Math.max(0.0265, 0.0250, 0.024, 0.031),执行的函数的thisMath。我不明白为什么它应该是Math 坦率地说,我认为该函数不需要有效的this。哦,这是一个正确的解释:stackoverflow.com/questions/21255138/…
  • Math.max(...array.map(o => o.y)) <3 thx to atom code formatter
【解决方案2】:

在对象数组中查找其属性“Y”具有最大值的对象

一种方法是使用 Array reduce..

const max = data.reduce(function(prev, current) {
    return (prev.y > current.y) ? prev : current
}) //returns object

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce http://caniuse.com/#search=reduce(IE9及以上)

如果您不需要支持 IE(仅 Edge),或者可以使用 Babel 等预编译器,则可以使用更简洁的语法。

const max = data.reduce((prev, current) => (prev.y > current.y) ? prev : current)

【讨论】:

  • 这是一个很好的答案,但是,您想传递一个初始值,否则如果数据数组为空,您会收到错误消息。即用于对象的自动增量索引。 const max = data.reduce((prev, current) =&gt; (prev.y &gt; current.y) ? prev : current, 1)
  • 你提出了一个很好的观点,我可能会选择null而不是1。
  • 请注意,这将返回具有最大值的对象,而不是对象的最大值。这可能是也可能不是您想要的。就我而言,这正是我想要的。 +1
  • 优秀的答案!起初,由于减少,我犹豫了,但无论如何我们都需要迭代,为什么不呢?
  • 这比公认的答案要好,因为使用大数组调用 apply 是不安全的,它可能导致堆栈溢出:stackoverflow.com/questions/30809656/…
【解决方案3】:

干净简单的 ES6 (Babel)

const maxValueOfY = Math.max(...arrayToSearchIn.map(o => o.y), 0);

如果arrayToSearchIn 为空,则第二个参数应确保默认值。

【讨论】:

  • 也很高兴知道它为空数组返回-Infinitytruthy 值)
  • 现在大多数没有 Babel 的现代浏览器都支持这一点。
  • 因为它为空数组返回-Infinity,所以您可以传递一个初始值Math.max(...state.allProjects.map(o =&gt; o.id), 1);
  • 这应该是现在公认的答案......绝对是更简洁的方法。
  • 如何在这里获取对象?
【解决方案4】:

三者比较单行者处理负数大小写(a 数组中的输入):

var maxA = a.reduce((a,b)=>a.y>b.y?a:b).y; // 30 chars time complexity:  O(n)

var maxB = a.sort((a,b)=>b.y-a.y)[0].y;    // 27 chars time complexity:  O(nlogn)
           
var maxC = Math.max(...a.map(o=>o.y));     // 26 chars time complexity: >O(2n)

可编辑示例here。来自:maxAmaxBmaxC 的想法(maxB 的副作用是数组 a 已更改,因为 sort 已就位)。

var a = [
  {"x":"8/11/2009","y":0.026572007},{"x":"8/12/2009","y":0.025057454},    
  {"x":"8/14/2009","y":0.031004457},{"x":"8/13/2009","y":0.024530916}
]

var maxA = a.reduce((a,b)=>a.y>b.y?a:b).y;
var maxC = Math.max(...a.map(o=>o.y));
var maxB = a.sort((a,b)=>b.y-a.y)[0].y;

document.body.innerHTML=`<pre>maxA: ${maxA}\nmaxB: ${maxB}\nmaxC: ${maxC}</pre>`;

对于更大的数组,Math.max... 将抛出异常:超出最大调用堆栈大小(Chrome 76.0.3809,Safari 12.1.2,日期 2019-09-13)

let a = Array(400*400).fill({"x": "8/11/2009", "y": 0.026572007 }); 

// Exception: Maximum call stack size exceeded

try {
  let max1= Math.max.apply(Math, a.map(o => o.y));
} catch(e) { console.error('Math.max.apply:', e.message) }

try {
  let max2= Math.max(...a.map(o=>o.y));
} catch(e) { console.error('Math.max-map:', e.message) }

Benchmark for the 4 element array

【讨论】:

  • 非常聪明的方法来完成任务。好的
  • 感谢您对可用选项的细分以及方法之间的差异。
  • 需要指出的一件事是,选项 B 通过在末尾省略 .y 可以更轻松地获得具有最大 y 值的整个对象。
  • 我不确定为什么maxA 的 Math.max() 有第二个参数?它应该只适用于var maxA = Math.max(...a.map(o=&gt;o.y));,不是吗?
  • @GreatHawkeye - 是的,你是对的 - 已修复 - 谢谢
【解决方案5】:

我想逐步解释terse accepted answer

var objects = [{ x: 3 }, { x: 1 }, { x: 2 }];

// array.map lets you extract an array of attribute values
var xValues = objects.map(function(o) { return o.x; });
// es6
xValues = Array.from(objects, o => o.x);

// function.apply lets you expand an array argument as individual arguments
// So the following is equivalent to Math.max(3, 1, 2)
// The first argument is "this" but since Math.max doesn't need it, null is fine
var xMax = Math.max.apply(null, xValues);
// es6
xMax = Math.max(...xValues);

// Finally, to find the object that has the maximum x value (note that result is array):
var maxXObjects = objects.filter(function(o) { return o.x === xMax; });

// Altogether
xMax = Math.max.apply(null, objects.map(function(o) { return o.x; }));
var maxXObject = objects.filter(function(o) { return o.x === xMax; })[0];
// es6
xMax = Math.max(...Array.from(objects, o => o.x));
maxXObject = objects.find(o => o.x === xMax);


document.write('<p>objects: ' + JSON.stringify(objects) + '</p>');
document.write('<p>xValues: ' + JSON.stringify(xValues) + '</p>');
document.write('<p>xMax: ' + JSON.stringify(xMax) + '</p>');
document.write('<p>maxXObjects: ' + JSON.stringify(maxXObjects) + '</p>');
document.write('<p>maxXObject: ' + JSON.stringify(maxXObject) + '</p>');

更多信息:

【讨论】:

  • 很好的解释!如果它不在代码 cmets 中,它可能会更容易阅读,但仍然 - 很棒的工作
【解决方案6】:

好吧,首先您应该解析 JSON 字符串,以便您可以轻松访问它的成员:

var arr = $.parseJSON(str);

使用map 方法提取值:

arr = $.map(arr, function(o){ return o.y; });

然后可以在max方法中使用数组:

var highest = Math.max.apply(this,arr);

或作为单行:

var highest = Math.max.apply(this,$.map($.parseJSON(str), function(o){ return o.y; }));

【讨论】:

  • 它没有标记jQuery
  • @RobinvanBaalen:是的,你是对的。然而,它被标记为 JSON,但接受的答案忽略了这一点,并且 tobyodavies 也从问题的主题中删除了它......也许我应该将 jquery 添加到问题中......;)
  • 如果@tobyodavies 忽略了它被标记为json 的事实并不重要——他在回答中没有使用外部javascript库:)
【解决方案7】:

这是最短的解决方案(One Liner)ES6

Math.max(...values.map(o => o.y));

【讨论】:

  • 同样,这对于大型数组是不安全的,因为它会导致堆栈溢出崩溃
【解决方案8】:

如果您(或这里的某个人)可以免费使用 lodash 实用程序库,它有一个maxBy在您的情况下非常方便的功能。

因此您可以这样使用:

_.maxBy(jsonSlice, 'y');

【讨论】:

    【解决方案9】:

    或者简单的排序!保持真实:)

    array.sort((a,b)=>a.y<b.y)[0].y
    

    【讨论】:

    • 好主意 +1(最短代码),但有一个小错误 - 将 a.y&lt;a.y 更改为 b.y-a.y。这里的时间复杂度比较:stackoverflow.com/a/53654364/860099
    • 找到最大值是 O(n)。这是 O(nlogn)。只要不牺牲效率,编写简单的代码是好的。
    • @Wildhammer - 实际上是Micro-optimisation is worth it when you have evidence that you're optimising a bottleneck.。在大多数情况下,简单的代码是比高效代码更好的选择。
    • @KamilKiełczewski 那篇文章中的两个数组比较具有相同的时间复杂度,不同之处在于它们的系数。例如,一个需要 n 个时间单位才能找到解决方案,而另一个需要 7n 个时间单位。在时间复杂度理论中,这两者都是 O(n)。我们在寻找最大值的问题中谈论的是 O(n) 与 O(n logn) 的比较。现在,如果您可以保证 n 不超过 10,那么您可以使用您的解决方案,否则 O(n) 算法始终是赢家,性能(用户体验)始终优先于开发人员体验(询问业内人士,他们会告诉您!) .
    • @Wildhammer 不——即使你的数组​​有 n=10000 个元素,用户也不会看到差异——证明HERE。性能优化仅适用于应用程序瓶颈(例如,您需要处理大型数组) - 但在大多数情况下,关注性能是错误的方法和浪费时间(=金钱)。这是众所周知的代码方法错误 - 阅读更多:“微优化”
    【解决方案10】:

    每个数组并使用 Math 获取最大值。

    data.reduce((max, b) => Math.max(max, b.costo), data[0].costo);
    

    【讨论】:

    • +1 但使用是的data.reduce((max, point) =&gt; Math.max(max, point.y), data[0].y); 许多其他答案会创建不必要的临时数组或进行昂贵的排序。使用减少()数学.max()内存和CPU效率高,可读性更强。
    【解决方案11】:

    它返回简化的对象@andy polhill answare

    var data=[
    {
    y:90
    },
    {
    y:9
    },
    {
    y:8
    }
    ]
    
    
    const max = data.reduce((prev, current)=> ( (prev.y > current.y) ? prev : current),0) //returns object
    console.log(max)

    【讨论】:

      【解决方案12】:
      var max = 0;                
      jQuery.map(arr, function (obj) {
        if (obj.attr > max)
          max = obj.attr;
      });
      

      【讨论】:

        【解决方案13】:

        ES6 解决方案

        Math.max(...array.map(function(o){return o.y;}))

        更多详情见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max

        【讨论】:

          【解决方案14】:

          又快又脏:

          Object.defineProperty(Array.prototype, 'min',
          {
              value: function(f)
              {
                  f = f || (v => v);
                  return this.reduce((a, b) => (f(a) < f(b)) ? a : b);
              }
          });
          
          Object.defineProperty(Array.prototype, 'max',
          {
              value: function(f)
              {
                  f = f || (v => v);
                  return this.reduce((a, b) => (f(a) > f(b)) ? a : b);
              }
          });
          
          console.log([1,2,3].max());
          console.log([1,2,3].max(x => x*(4-x)));
          console.log([1,2,3].min());
          console.log([1,2,3].min(x => x*(4-x)));

          【讨论】:

            【解决方案15】:

            接受答案的解释和更通用的方法

            如果有人在这里找到所有这些键中的最大值(一种通用方式):

            const temp1 = [
                {
                    "name": "Month 8 . Week 1",
                    "CATEGORY, Id 0": null,
                    "CATEGORY, Id 1": 30.666666666666668,
                    "CATEGORY, Id 2": 17.333333333333332,
                    "CATEGORY, Id 3": 12.333333333333334,
                    "TASK, Id 1": 30.666666666666668,
                    "TASK, Id 2": 12.333333333333334,
                    "TASK, Id 3": null,
                    "TASK, Id 4": 5,
                    "TASK, Id 5": null,
                    "TASK, Id 6": null,
                    "TASK, Id 7": null,
                    "TASK, Id 8": null,
                    "TASK, Id 9": null,
                    "TASK, Id 10": null,
                    "TASK, Id 12": null,
                    "TASK, Id 14": null,
                    "TASK, Id 16": null,
                    "TASK, Id 17": null,
                    "TASK, Id 26": 12.333333333333334
                },
                {
                    "name": "Month 8 . Week 2",
                    "CATEGORY, Id 0": 38,
                    "CATEGORY, Id 1": null,
                    "CATEGORY, Id 2": 12,
                    "CATEGORY, Id 3": null,
                    "TASK, Id 1": null,
                    "TASK, Id 2": 15,
                    "TASK, Id 3": null,
                    "TASK, Id 4": null,
                    "TASK, Id 5": null,
                    "TASK, Id 6": 5,
                    "TASK, Id 7": 5,
                    "TASK, Id 8": 5,
                    "TASK, Id 9": 5,
                    "TASK, Id 10": null,
                    "TASK, Id 12": null,
                    "TASK, Id 14": null,
                    "TASK, Id 16": null,
                    "TASK, Id 17": null,
                    "TASK, Id 26": 15
                },
                {
                    "name": "Month 8 . Week 3",
                    "CATEGORY, Id 0": 7,
                    "CATEGORY, Id 1": 12.333333333333334,
                    "CATEGORY, Id 2": null,
                    "CATEGORY, Id 3": null,
                    "TASK, Id 1": null,
                    "TASK, Id 2": null,
                    "TASK, Id 3": 12.333333333333334,
                    "TASK, Id 4": null,
                    "TASK, Id 5": null,
                    "TASK, Id 6": null,
                    "TASK, Id 7": null,
                    "TASK, Id 8": null,
                    "TASK, Id 9": null,
                    "TASK, Id 10": null,
                    "TASK, Id 12": null,
                    "TASK, Id 14": 7,
                    "TASK, Id 16": null,
                    "TASK, Id 17": null,
                    "TASK, Id 26": null
                },
                {
                    "name": "Month 8 . Week 4",
                    "CATEGORY, Id 0": null,
                    "CATEGORY, Id 1": null,
                    "CATEGORY, Id 2": 10,
                    "CATEGORY, Id 3": 5,
                    "TASK, Id 1": null,
                    "TASK, Id 2": null,
                    "TASK, Id 3": null,
                    "TASK, Id 4": null,
                    "TASK, Id 5": 5,
                    "TASK, Id 6": null,
                    "TASK, Id 7": null,
                    "TASK, Id 8": null,
                    "TASK, Id 9": null,
                    "TASK, Id 10": 5,
                    "TASK, Id 12": 5,
                    "TASK, Id 14": null,
                    "TASK, Id 16": null,
                    "TASK, Id 17": null,
                    "TASK, Id 26": null
                },
                {
                    "name": "Month 8 . Week 5",
                    "CATEGORY, Id 0": 5,
                    "CATEGORY, Id 1": null,
                    "CATEGORY, Id 2": 7,
                    "CATEGORY, Id 3": null,
                    "TASK, Id 1": null,
                    "TASK, Id 2": null,
                    "TASK, Id 3": null,
                    "TASK, Id 4": null,
                    "TASK, Id 5": null,
                    "TASK, Id 6": null,
                    "TASK, Id 7": null,
                    "TASK, Id 8": null,
                    "TASK, Id 9": null,
                    "TASK, Id 10": null,
                    "TASK, Id 12": null,
                    "TASK, Id 14": null,
                    "TASK, Id 16": 7,
                    "TASK, Id 17": 5,
                    "TASK, Id 26": null
                },
                {
                    "name": "Month 9 . Week 1",
                    "CATEGORY, Id 0": 13.333333333333334,
                    "CATEGORY, Id 1": 13.333333333333334,
                    "CATEGORY, Id 3": null,
                    "TASK, Id 11": null,
                    "TASK, Id 14": 6.333333333333333,
                    "TASK, Id 17": null,
                    "TASK, Id 18": 7,
                    "TASK, Id 19": null,
                    "TASK, Id 20": null,
                    "TASK, Id 26": 13.333333333333334
                },
                {
                    "name": "Month 9 . Week 2",
                    "CATEGORY, Id 0": null,
                    "CATEGORY, Id 1": null,
                    "CATEGORY, Id 3": 13.333333333333334,
                    "TASK, Id 11": 5,
                    "TASK, Id 14": null,
                    "TASK, Id 17": 8.333333333333334,
                    "TASK, Id 18": null,
                    "TASK, Id 19": null,
                    "TASK, Id 20": null,
                    "TASK, Id 26": null
                },
                {
                    "name": "Month 9 . Week 3",
                    "CATEGORY, Id 0": null,
                    "CATEGORY, Id 1": 14,
                    "CATEGORY, Id 3": null,
                    "TASK, Id 11": null,
                    "TASK, Id 14": null,
                    "TASK, Id 17": null,
                    "TASK, Id 18": null,
                    "TASK, Id 19": 7,
                    "TASK, Id 20": 7,
                    "TASK, Id 26": null
                }
            ]
            
            console.log(Math.max(...[].concat([], ...temp1.map(i => Object.values(i))).filter(v => typeof v === 'number')))

            需要注意的一件事是Math.max(1, 2, 3) 返回3Math.max(...[1, 2, 3]) 也是如此,因为 Spread syntax can be used when all elements from an object or array need to be included in a list of some kind.

            我们将利用这一点!

            让我们假设一个看起来像这样的数组:

            var a = [{a: 1, b: 2}, {foo: 12, bar: 141}]
            

            目标是找到最大值(在任何属性中),(这里是bar(141))

            所以要使用Math.max(),我们需要一个数组中的值(所以我们可以这样做...arr

            首先让我们把所有的数字分开 我们可以认为数组a 的每一项都是一个对象。 在遍历它们中的每一个时,Object.values(item) 将以数组形式为我们提供该项目的所有值,我们可以使用 map 生成一个只有值的新数组

            所以,

            var p = a.map(item => Object.values(item)) // [ [1, 2], [12, 141] ]
            

            另外,使用concat

            [].concat([], ...arr), or just [].concat(...arr) on arr, [ [1, 2], [12, 141] ] flattens it to [1, 2, 12, 141]

            所以,

            var f = [].concat(...p) // [1, 2, 12, 141]
            

            因为我们现在有一个只有数字的数组,所以我们执行 Math.max(...f):

            var m = Math.max(...f) // 141
            

            【讨论】:

              【解决方案16】:

              感谢我在这里找到的答案,我希望它对某人有用。 可以调用这个打字稿函数来搜索可以存在于数组对象字段中的最大值:

              function getHighestField(objArray: any[], fieldName: string) {
                return Number(
                  Math.max.apply(
                    Math,
                    objArray?.map(o => o[fieldName] || 0),
                  ) || 0,
                );
              }
              

              以此值为例:

              const scoreBoard = [
                { name: 'player1', score: 4 },
                { name: 'player2', score: 9 },
                { name: 'player3', score: 7 }
              ]
              

              你可以这样调用函数:

              const myHighestVariable = `This is the highest: ${getHighestField(scoreBoard, "score")}`;
              

              结果将是这样的:

              console.log(myHighestVariable);
              

              这是最高的:9

              【讨论】:

                【解决方案17】:
                // Here is very simple way to go:
                
                // Your DataSet.
                
                let numberArray = [
                  {
                    "x": "8/11/2009",
                    "y": 0.026572007
                  },
                  {
                    "x": "8/12/2009",
                    "y": 0.025057454
                  },
                  {
                    "x": "8/13/2009",
                    "y": 0.024530916
                  },
                  {
                    "x": "8/14/2009",
                    "y": 0.031004457
                  }
                ]
                
                // 1. First create Array, containing all the value of Y
                let result = numberArray.map((y) => y)
                console.log(result) // >> [0.026572007,0.025057454,0.024530916,0.031004457]
                
                // 2.
                let maxValue = Math.max.apply(null, result)
                console.log(maxValue) // >> 0.031004457
                

                【讨论】:

                  【解决方案18】:

                  这很简单

                       const array1 = [
                    {id: 1, val: 60},
                    {id: 2, val: 2},
                    {id: 3, val: 89},
                    {id: 4, val: 78}
                  ];
                  const array2 = [1,6,8,79,45,21,65,85,32,654];
                  const max = array1.reduce((acc, item) => acc = acc > item.val ? acc : item.val, 0);
                  const max2 = array2.reduce((acc, item) => acc = acc > item ? acc : item, 0);
                  
                  console.log(max);
                  console.log(max2);
                  

                  【讨论】:

                    【解决方案19】:
                    const getMaxFromListByField = (list, field) => { 
                        return list[list.map(it => it[field]).indexOf(Math.max(...list.map(it => it[field])))] 
                    }
                    

                    【讨论】:

                    • 请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。
                    【解决方案20】:
                    let List= [{votes:4},{votes:8},{votes:7}]
                    
                    let objMax = List.reduce((max, curren) => max.votes > curren.votes ? max : curren);
                    
                    console.log(objMax)
                    

                    【讨论】:

                    • 请不要只用代码 sn-p 回答。尝试解释您对该主题的贡献或您的答案与其他人的不同之处。
                    猜你喜欢
                    • 1970-01-01
                    • 2014-05-07
                    • 2018-07-09
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-09-14
                    • 1970-01-01
                    相关资源
                    最近更新 更多