在对象数组中查找属性的最大值


413

我正在寻找一种非常快速,干净和有效的方法来获取以下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-loop是解决此问题的唯一方法吗?我热衷于使用Math.max


4
您将如何返回对象,而不仅是找到的最小attr值?
Mike Lyons 2014年

1
为了我自己的利益,我对此进行了一些快速性能测试。jsperf.com/finding-the-max-value-an-array-of-objects
Andy Polhill

Answers:


739

要在中找到y对象的最大值array

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

47
您能否扩展此答案以显示如何返回发现最大值的对象?那将非常有帮助,谢谢!
Mike Lyons 2014年

19
这是小提琴!希望这将对某人有所
mili

24
@MikeLyons,如果您仍然关心获取实际对象:jsfiddle.net/45c5r246/34
tobyodavies 2015年

11
请说明您的答案!
约翰·威廉·多明戈

12
FWIW我的理解是,当您在函数上调用apply时,它将以指定的值this和一系列指定为数组的参数执行该函数。诀窍是apply会将数组变成一系列实际的函数参数。因此,在这种情况下,它最终Math.max(0.0265, 0.0250, 0.024, 0.031)this执行的函数are进行调用Math。我不明白为什么应该Math坦率地说,我认为该函数不需要有效的this。哦,这里是一个正确的解释:stackoverflow.com/questions/21255138/...
丹尼尔ç

262

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

一种方法是使用Array reduce ..

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

https://developer.mozilla.org/zh-CN/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)

7
这是一个很好的答案,但是,如果数据数组为空,则您想传递一个初始值,否则会出错。即用于对象的自动增量索引。 const max = data.reduce((prev, current) => (prev.y > current.y) ? prev : current, 1)
juliangonzalez

2
你养好点,我可能会选择null在1
安迪Polhill

25
请注意,这将返回具有最大值而不是来自该对象的最大值的对象。这可能是您想要的,也可能不是。就我而言,这就是我想要的。+1
John

1
好的补充答案!
传奇

很好的答案!起初,我由于减少而有所犹豫,但是无论如何我们都需要迭代,所以为什么不呢?
shapiro yaacov

146

简洁的ES6(Babel)

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

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


8
也很高兴知道它为一个空数组返回-Infinity真实值)
icl7126 '16

1
现在没有Babel的大多数现代浏览器都支持此功能。
Eugene Kulabuhov '17

20
当它返回-Infinity一个空数组时,您可以传递一个初始值 Math.max(...state.allProjects.map(o => o.id), 1);
juliangonzalez,2017年

5
这应该是现在可以接受的答案了……绝对是更简洁的方法。
尼克

1
处理负值的大小写更改0arrayToSearchIn[0].y。时间复杂度比较:stackoverflow.com/a/53654364/860099
KamilKiełczewski18年

40

处理负数大小写的树ONELINERS的比较(在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)

可编辑的示例在这里。来自maxAmaxBmaxC的想法(maxB的副作用是因为数组就位a而更改了数组sort)。

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


2
非常聪明的方法来完成任务。尼斯
TetraDev '19

抱歉,被误认为是错误的,并且由于编辑时间过长而无法编辑您的问题而无法撤消。
君特Zöchbauer

非常感谢您的分析。
d337

感谢您对可用选项的细分以及方法之间的差异。
FistOfFury

需要指出的一件事是,选项B y通过.y在末尾省略,更容易获得具有最大值的整个对象。
FistOfFury

23

好吧,首先您应该解析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; }));

15
未标记为jQuery
Robin van Baalen 2014年

1
@RobinvanBaalen:是的,你是对的。但是,它用JSON标记,但是被接受的答案忽略了这一点,并且tobyodavies还将其从问题的主题中删除了……也许我应该在问题中添加jquery…;)
Guffa 2014年

8
@tobyodavies忽略它被标记的事实没关系json-他在回答中没有使用外部javascript库:)
Robin van Baalen 2014年

23

我想逐步解释简短的答案

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>');

更多的信息:


很好的解释!如果不是在代码注释中,可能会更容易阅读,但仍然-很棒的工作
Martin

12
var data = [
  { 'name': 'Vins', 'age': 27 },
  { 'name': 'Jan', 'age': 38 },
  { 'name': 'Alex', 'age': 80 },
  { 'name': 'Carl', 'age': 25 },
  { 'name': 'Digi', 'age': 40 }
];
var max = data.reduce(function (prev, current) {
   return (prev.age > current.age) ? prev : current
});
//output = {'name': 'Alex', 'age': 80}

2
这与@AndyPolhill的答案有何不同?
刘易斯

7

如果您(或这里的某人)可以自由使用lodash实用程序库,则它具有maxBy函数,在您的情况下非常方便。

因此您可以这样使用:

_.maxBy(jsonSlice, 'y');

5

还是简单的排序!保持真实:)

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

不错的主意+1(最短的代码),但是有个小错误-更改a.y<a.yb.y-a.y。这里的时间复杂度比较:stackoverflow.com/a/53654364/860099
KamilKiełczewski18年

2
求最大值为O(n)。这是O(nlogn)。只要不牺牲效率,编写简单的代码就可以。
Wildhammer

@Wildhammer- 当您有证据证明您正在优化瓶颈时,微优化实际上是值得的。。在大多数情况下,简单代码是比高效代码更好的选择。
KamilKiełczewski

@KamilKiełczewski该文章中的两个数组比较都具有相同的时间复杂度,只是系数不同。例如,一个以n个时间单位来寻找解决方案,而另一个以7n为单位。在时间复杂度理论中,这两个均为O(n)。我们在寻找最大值的问题中所谈论的是O(n)与O(n logn)的比较。现在,如果可以保证n不超过10,则可以使用您的解决方案,否则O(n)算法始终是赢家,而性能(用户体验)始终要优先于开发人员经验(问行业人士,他们告诉您!) 。
Wildhammer,

@Wildhammer nope-即使您的数组具有n = 10000个元素,用户也不会在此处看到差异证明。性能优化仅对应用程序瓶颈有效(例如,您需要处理大型阵列)-但在大多数情况下,以性能为中心是错误的方法,并且浪费时间(=金钱)。这是一个众所周知的代码处理错误-阅读更多:“微优化”
KamilKiełczewski


1
var max = 0;                
jQuery.map(arr, function (obj) {
  if (obj.attr > max)
    max = obj.attr;
});


1
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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.