Program Tip

최소 / 최대를 얻기 위해 자바 스크립트 객체 배열 비교

programtip 2020. 10. 15. 21:26
반응형

최소 / 최대를 얻기 위해 자바 스크립트 객체 배열 비교


개체 배열이 있고 특정 개체 속성에서 해당 개체를 비교하고 싶습니다. 내 배열은 다음과 같습니다.

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

구체적으로 "비용"에 초점을 맞추고 최소값과 최대 값을 얻고 싶습니다. 비용 값을 가져 와서 자바 스크립트 배열로 밀어 넣은 다음 Fast JavaScript Max / Min 을 실행할 수 있다는 것을 알고 있습니다 .

그러나 중간에있는 배열 단계를 건너 뛰고 개체 속성 (이 경우 "비용")을 직접 해제하는 더 쉬운 방법이 있습니까?


이 경우 가장 빠른 방법은 모든 요소를 ​​반복하여 지금까지의 최고 / 최저 값과 비교하는 것입니다.

(배열을 만들고 배열 메서드를 호출하는 것은이 간단한 작업에 과잉입니다).

 // There's no real number bigger than plus Infinity
var lowest = Number.POSITIVE_INFINITY;
var highest = Number.NEGATIVE_INFINITY;
var tmp;
for (var i=myArray.length-1; i>=0; i--) {
    tmp = myArray[i].Cost;
    if (tmp < lowest) lowest = tmp;
    if (tmp > highest) highest = tmp;
}
console.log(highest, lowest);

감소는 다음과 같은 작업에 유용합니다. 객체 배열에 대해 집계 작업 (최소, 최대, 평균 등)을 수행하고 단일 결과를 반환합니다.

myArray.reduce(function(prev, curr) {
    return prev.Cost < curr.Cost ? prev : curr;
});

... 또는 ES6 함수 구문으로 내부 함수를 정의 할 수 있습니다.

(prev, curr) => prev.Cost < curr.Cost ? prev : curr

귀엽고 싶다면 이것을 배열에 붙일 수 있습니다.

Array.prototype.hasMin = function(attrib) {
    return (this.length && this.reduce(function(prev, curr){ 
        return prev[attrib] < curr[attrib] ? prev : curr; 
    })) || null;
 }

이제 다음과 같이 말할 수 있습니다.

myArray.hasMin('ID')  // result:  {"ID": 1, "Cost": 200}
myArray.hasMin('Cost')    // result: {"ID": 3, "Cost": 50}
myEmptyArray.hasMin('ID')   // result: null

이것을 사용하려는 경우 모든 상황에 대한 전체 검사가있는 것은 아닙니다. 기본 유형의 배열을 전달하면 실패합니다. 존재하지 않는 속성을 확인하거나 모든 개체에 해당 속성이 포함되어 있지 않은 경우 마지막 요소를 가져옵니다. 이 버전은 좀 더 부피가 크지 만 다음과 같은 검사가 있습니다.

Array.prototype.hasMin = function(attrib) {
    const checker = (o, i) => typeof(o) === 'object' && o[i]
    return (this.length && this.reduce(function(prev, curr){
        const prevOk = checker(prev, attrib);
        const currOk = checker(curr, attrib);
        if (!prevOk && !currOk) return {};
        if (!prevOk) return curr;
        if (!currOk) return prev;
        return prev[attrib] < curr[attrib] ? prev : curr; 
    })) || null;
 }

sort수정되는 배열에 대해 신경 쓰지 않는 경우를 사용하십시오 .

myArray.sort(function (a, b) {
    return a.Cost - b.Cost
})

var min = myArray[0],
    max = myArray[myArray.length - 1]

내 생각 롭 W의 대답은 정말 올바른 (+1)이지만, 단지 재미를 위해 : 당신은 "영리"이 원한다면, 당신은 할 수 같은 것을 할 :

var myArray = 
[
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

function finder(cmp, arr, attr) {
    var val = arr[0][attr];
    for(var i=1;i<arr.length;i++) {
        val = cmp(val, arr[i][attr])
    }
    return val;
}

alert(finder(Math.max, myArray, "Cost"));
alert(finder(Math.min, myArray, "Cost"));

또는 깊게 중첩 된 구조가있는 경우 좀 더 기능적으로 다음을 수행 할 수 있습니다.

var myArray = 
[
    {"ID": 1, "Cost": { "Wholesale":200, Retail: 250 }},
    {"ID": 2, "Cost": { "Wholesale":1000, Retail: 1010 }},
    {"ID": 3, "Cost": { "Wholesale":50, Retail: 300 }},
    {"ID": 4, "Cost": { "Wholesale":500, Retail: 1050 }}
]

function finder(cmp, arr, getter) {
    var val = getter(arr[0]);
    for(var i=1;i<arr.length;i++) {
        val = cmp(val, getter(arr[i]))
    }
    return val;
}

alert(finder(Math.max, myArray, function(x) { return x.Cost.Wholesale; }));
alert(finder(Math.min, myArray, function(x) { return x.Cost.Retail; }));

이것들은 더 유용하고 특정한 형태로 쉽게 커리 될 수 있습니다.


Math함수를 사용 하고 원하는 값을 map.

다음은 jsbin입니다.

https://jsbin.com/necosu/1/edit?js,console

var myArray = [{
    "ID": 1,
    "Cost": 200
  }, {
    "ID": 2,
    "Cost": 1000
  }, {
    "ID": 3,
    "Cost": 50
  }, {
    "ID": 4,
    "Cost": 500
  }],

  min = Math.min.apply(null, myArray.map(function(item) {
    return item.Cost;
  })),
  max = Math.max.apply(null, myArray.map(function(item) {
    return item.Cost;
  }));

console.log('min', min);//50
console.log('max', max);//1000

최신 정보:

ES6를 사용하려는 경우 :

var min = Math.min.apply(null, myArray.map(item => item.Cost)),
    max = Math.max.apply(null, myArray.map(item => item.Cost));

이것은 더 나은 솔루션입니다

    var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
    ]
    var lowestNumber = myArray[0].Cost;
    var highestNumber = myArray[0].Cost;

    myArray.forEach(function (keyValue, index, myArray) {
      if(index > 0) {
        if(keyValue.Cost < lowestNumber){
          lowestNumber = keyValue.Cost;
        }
        if(keyValue.Cost > highestNumber) {
          highestNumber = keyValue.Cost;
        }
      }
    });
    console.log('lowest number' , lowestNumber);
    console.log('highest Number' , highestNumber);

Array.prototype.reduce ()를 사용하면 비교기 함수를 연결하여 배열의 최소, 최대 등 항목을 결정할 수 있습니다.

var items = [
  { name : 'Apple',  count : 3  },
  { name : 'Banana', count : 10 },
  { name : 'Orange', count : 2  },
  { name : 'Mango',  count : 8  }
];

function findBy(arr, key, comparatorFn) {
  return arr.reduce(function(prev, curr, index, arr) { 
    return comparatorFn.call(arr, prev[key], curr[key]) ? prev : curr; 
  });
}

function minComp(prev, curr) {
  return prev < curr;
}

function maxComp(prev, curr) {
  return prev > curr;
}

document.body.innerHTML  = 'Min: ' + findBy(items, 'count', minComp).name + '<br />';
document.body.innerHTML += 'Max: ' + findBy(items, 'count', maxComp).name;


Adding onto Tristan Reid's answer (+ using es6), you could create a function that accepts a callback, which will contain the operator you want to be applied to the prev and curr:

const compare = (arr, key, callback) => arr.reduce((prev, curr) =>
    (callback(prev[key], curr[key]) ? prev : curr), {})[key];

    // remove `[key]` to return the whole object

Then you could simply call it using:

const costMin = compare(myArray, 'Cost', (a, b) => a < b);
const costMax = compare(myArray, 'Cost', (a, b) => a > b);

This can be achieved with lodash's minBy and maxBy functions.

Lodash's minBy and maxBy documentation

_.minBy(array, [iteratee=_.identity])

_.maxBy(array, [iteratee=_.identity])

These methods accept an iteratee which is invoked for each element in array to generate the criterion by which the value is ranked. The iteratee is invoked with one argument: (value).

Solution

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]

const minimumCostItem = _.minBy(myArray, "Cost");

console.log("Minimum cost item: ", minimumCostItem);

// Getting the maximum using a functional iteratee
const maximumCostItem = _.maxBy(myArray, function(entry) {
  return entry["Cost"];
});

console.log("Maximum cost item: ", maximumCostItem);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>


Another one, similar to Kennebec's answer, but all in one line:

maxsort = myArray.slice(0).sort(function (a, b) { return b.ID - a.ID })[0].ID; 

You can use built-in Array object to use Math.max/Math.min instead:

var arr = [1,4,2,6,88,22,344];

var max = Math.max.apply(Math, arr);// return 344
var min = Math.min.apply(Math, arr);// return 1

참고URL : https://stackoverflow.com/questions/8864430/compare-javascript-array-of-objects-to-get-min-max

반응형