객체 배열에서 속성의 최대 값 찾기


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 2018 년

1
내 자신의 이익을 위해 나는 이것에 대한 빠른 성능 테스트를 수행했다. jsperf.com/finding-the-max-value-an-array-of-objects
Andy Polhill

1
jsbin.com/pagamujuge/edit?html,js,console 솔루션의 JSBin
Andy Polhill

답변:


739

y에서 객체 의 최대 값 을 찾으려면 array:

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

47
이 값을 확장하여 최대 값이 발견 된 객체를 반환하는 방법을 보여줄 수 있습니까? 매우 도움이 될 것입니다. 감사합니다!
Mike Lyons 2018 년

19
여기 바이올린이 있습니다! 이것이 누군가 에게
mili

24
@MikeLyons 여전히 실제 객체를 얻는 것에 관심이 있다면 : jsfiddle.net/45c5r246/34
tobyodavies

11
답을 설명하십시오!
John William Domingo

12
FWIW 내 이해는 함수에서 apply를 호출하면 지정된 값 this과 배열로 지정된 일련의 인수 로 함수를 실행합니다 . 비결은 적용이 배열을 일련의 실제 함수 인수로 바꾸는 것입니다. 따라서이 경우 에는 함수가 실행 된 상태로 호출 Math.max(0.0265, 0.0250, 0.024, 0.031)됩니다 . 왜 솔직 해야하는지 알 수 없습니다 . 함수가 필요하다고 생각하지 않습니다 . 아, 그리고 여기에 적절한 설명이 있습니다 : stackoverflow.com/questions/21255138/…thisMathMaththis
Daniel C

263

객체 배열에서 "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)

7
이것은 좋은 대답이지만 초기 값을 전달하거나 데이터 배열이 비어있는 경우 오류가 발생합니다. 즉, 객체의 자동 증가 색인에 대한 것입니다. const max = data.reduce((prev, current) => (prev.y > current.y) ? prev : current, 1)
juliangonzalez

2
당신은 좋은 점을 제기, 아마 null1 이상을 선택합니다 .
Andy Polhill

25
객체의 최대 값이 아닌 최대 값을 가진 객체를 반환합니다. 이것은 당신이 원하는 것일 수도 아닐 수도 있습니다. 제 경우에는 제가 원했던 것이 었습니다. +1
John

1
좋은 보완 답변!
Legends

훌륭한 답변! 처음에는 축소로 인해 망설 였지만 어쨌든 반복해야합니까?
shapiro yaacov

146

깨끗하고 간단한 ES6 (바벨)

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

두 번째 매개 변수 arrayToSearchIn는 비어있는 경우 기본값을 보장해야합니다 .


8
또한 빈 배열에 대해 -Infinity( 진실한 값)을 반환한다는 것을 아는 것이 좋습니다
icl7126

1
이것은 현재 Babel이없는 대부분의 최신 브라우저에서 지원됩니다.
유진 쿨라 부 호프

20
이 반환로 -Infinity는 하늘의 배열을 위해, 당신은 통과 할 수 초기 값 Math.max(...state.allProjects.map(o => o.id), 1);
juliangonzalez

5
이것은 지금 받아 들여지는 대답이어야합니다 ... 확실히 더 간결한 접근법입니다.
nick16

1
빼기 값의 대소 문자를 처리하려면 0로 변경 하십시오 arrayToSearchIn[0].y. 시간 복잡성 비교 : stackoverflow.com/a/53654364/860099
Kamil Kiełczewski

41

마이너스 숫자 대 / 소문자를 처리하는 트리 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)

여기에서 편집 가능한 예 입니다. maxA , maxBmaxC의 아이디어 ( maxB의 부작용은 배열 asort제자리에 있기 때문에 배열 이 변경 된다는 것입니다).

더 큰 배열의 Math.max...경우 예외가 발생합니다. 최대 호출 스택 크기를 초과했습니다 (Chrome 76.0.3809, Safari 12.1.2, 날짜 2019-09-13)


2
작업을 수행하는 매우 영리한 방법. 니스
TetraDev

죄송합니다. 실수로 다운 봇이 발생했으며 시간이 너무 많이 소요되어 질문을 수정하지 않으면 실행 취소 할 수 없습니다.
Günter 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

1
@RobinvanBaalen : 그렇습니다. 그러나 JSON으로 태그가 지정되었지만 허용 된 답변은이를 무시하고 tobyodavies도 질문 주제에서이를 제거했습니다 ... 아마도 질문에 jquery를 추가해야합니다 ...;)
Guffa

8
@tobyodavies가이 태그 된 사실을 무시하는 경우는별로 중요하지 않습니다 json그는 :) 그의 대답에 외부 자바 스크립트 라이브러리를 사용하지 않는 -
로빈 반 Baalen

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의 답변과 어떻게 다릅니 까?
Lewis

7

당신 (또는 여기 누군가)이 lodash유틸리티 라이브러리를 자유롭게 사용할 수 있다면 maxBy 기능이있어 귀하의 경우에 매우 편리합니다.

따라서 다음과 같이 사용할 수 있습니다.

_.maxBy(jsonSlice, 'y');

6

아니면 간단한 종류! 그것을 진짜로 유지 :)

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

좋은 아이디어 +1 (가장 짧은 코드)이지만 작은 버그 변경 a.y<a.yb.y-a.y있습니다. 시간 복잡성 비교 : stackoverflow.com/a/53654364/860099
Kamil Kiełczewski

2
최대 값을 구하는 것은 O (n)입니다. 이것은 O (nlogn)입니다. 효율성이 저하되지 않는 한 간단한 코드를 작성하는 것이 좋습니다.
Wildhammer

@Wildhammer-실제로 병목 현상을 최적화하고 있다는 증거가있을 때 마이크로 최적화가 그만한 가치가 있습니다. . 대부분의 경우 간단한 코드가 고효율 코드보다 더 나은 선택입니다.
Kamil Kiełczewski

@ KamilKiełczewski이 기사의 두 배열 비교는 계수의 차이가 같은 시간 복잡성을가집니다. 예를 들어, 하나는 솔루션을 찾는 데 n 시간 단위가 걸리고 다른 하나는 7n입니다. 시간 복잡성 이론에서, 둘 다 O (n)입니다. max를 찾는 문제에서 우리가 이야기하고있는 것은 O (n)과 O (n logn)의 비교입니다. 이제 n이 10을 초과하지 않는다는 것을 보장 할 수 있다면 솔루션을 사용할 수 있습니다. 그렇지 않으면 O (n) 알고리즘이 항상 승자이며 성능 (사용자 경험)이 개발자 경험보다 항상 앞서 있습니다 (업계 종사자에게 물어보십시오!) .
Wildhammer

@Wildhammer nope-배열에 n = 10000 개의 요소가 있더라도 사용자는 여기에서 차이 증명을 볼 수 없습니다 . 성능 최적화는 앱 병목 현상에만 효과적입니다 (예 : 대규모 배열을 처리해야 함). 대부분의 경우 성능 중심은 잘못된 접근 방식과 시간 (= 돈) 낭비입니다. 이것은 잘 알려진 코드 접근 실수입니다. 더 읽기 : "마이크로 최적화"
Kamil Kiełczewski


2

가장 짧은 솔루션 (One Liner) ES6 는 다음과 같습니다 .

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

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.