source

객체의 JavaScript 배열을 최소/최대 값으로 비교

factcode 2023. 11. 5. 15:01
반응형

객체의 JavaScript 배열을 최소/최대 값으로 비교

객체 배열을 가지고 있는데 특정 객체 속성에서 이 객체들을 비교하려고 합니다.여기 제 배열이 있습니다.

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

저는 구체적으로 "비용"을 제로로 하고 최소값과 최대값을 얻고 싶습니다.비용 값을 잡아 자바스크립트 배열에 밀어 넣은 다음 빠른 자바스크립트 Max/Min을 실행할 수 있다는 것을 깨달았습니다.

그러나 배열 단계를 중간에 무시하고 개체 속성(이 경우 "비용")을 직접 꺼서 이를 더 쉽게 수행할 수 있는 방법이 있습니까?

Array.prototype.reduce() 어레이에서 집계 작업(min, max, avg 등)을 수행하고 단일 결과를 반환하는 것은 다음과 같은 경우에 적합합니다.

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

...또는 ES6 함수 구문을 사용하여 내부 함수를 정의할 수 있습니다.

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

귀여운 모습을 보여주고 싶다면 Array 프로토타입에 다음을 첨부하면 됩니다.

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;
 }

한 가지 방법은 모든 요소를 순환시켜 최고/최저 값과 비교하는 것입니다.

(이러한 단순한 작업에서 배열을 생성하고 배열 메서드를 호출하는 것은 과도한 작업입니다.)

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

사용.Math.min그리고.Math.max:

var myArray = [
    { id: 1, cost: 200},
    { id: 2, cost: 1000},
    { id: 3, cost: 50},
    { id: 4, cost: 500}
]


var min = Math.min(...myArray.map(item => item.cost));
var max = Math.max(...myArray.map(item => item.cost));

console.log("min: " + min);
console.log("max: " + max);

배열을 수정해도 상관없는 경우 를 사용합니다.

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

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

사용하다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));

시도()ais 배열,f비교할 필드)

let max= (a,f)=> a.reduce((m,x)=> m[f]>x[f] ? m:x);
let min= (a,f)=> a.reduce((m,x)=> m[f]<x[f] ? m:x);

let max= (a,f)=> a.reduce((m,x)=> m[f]>x[f] ? m:x);
let min= (a,f)=> a.reduce((m,x)=> m[f]<x[f] ? m:x);

// TEST

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

console.log('Max Cost', max(myArray, 'Cost'));
console.log('Min Cost', min(myArray, 'Cost'));

console.log('Max ID', max(myArray, 'ID'));
console.log('Min ID', min(myArray, 'ID'));

Rob 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.max.apply(Math, myArray.map(a => a.Cost));

분간

Math.min.apply(Math, myArray.map(a => a.Cost));

이는 Lodash's를 통해 달성할 수 있습니다.minBy그리고.maxBy기능들.

로다시스minBy그리고.maxBy문서화

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

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

이 메서드는 배열의 각 요소에 대해 호출되는 반복을 허용하여 값의 순위가 매겨지는 기준을 생성합니다.반복은 (value)라는 하나의 인수로 호출됩니다.

해결책

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>

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;

간결하고 현대적인 솔루션을 위해서는 현재 최소값과 최대값을 추적하여 어레이에 대한 연산을 수행할 수 있으므로 어레이를 한 번만 반복할 수 있습니다(최적입니다).

let [min, max] = myArray.reduce(([prevMin,prevMax], {Cost})=>
   [Math.min(prevMin, Cost), Math.max(prevMax, Cost)], [Infinity, -Infinity]);

데모:

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]
let [min, max] = myArray.reduce(([prevMin,prevMax], {Cost})=>
   [Math.min(prevMin, Cost), Math.max(prevMax, Cost)], [Infinity, -Infinity]);
console.log("Min cost:", min);
console.log("Max cost:", max);

이것이 더 나은 해결책입니다.

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

트리스탄 리드의 답변(+ es6 사용)에 추가하여 콜백을 수락하는 함수를 만들 수 있습니다. 여기에는 적용할 연산자가 포함됩니다.prev그리고.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

그러면 다음을 사용하여 간단히 호출할 수 있습니다.

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

우리는 두가지 방법으로 문제를 해결할 수 있습니다. 두 방법 모두 위에서 이미 설명했지만 성능 테스트가 누락되어 하나를 완성했습니다.

1, 네이티브 자바 스크립트 방식
2, 먼저 정렬된 개체를 정렬한 다음 정렬된 개체에서 min max를 쉽게 얻을 수 있습니다.

나는 또한 양쪽 토우 접근법의 성능을 테스트합니다.

실행하고 성능을 테스트할 수도 있습니다.해피코딩(:

//first approach 

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

var t1 = performance.now();;

let max=Math.max.apply(Math, myArray.map(i=>i.Cost))

let min=Math.min.apply(Math, myArray.map(i=>i.Cost))

var t2   = performance.now();;

console.log("native fuction took " + (t2 - t1) + " milliseconds.");

console.log("max Val:"+max)
console.log("min Val:"+min)

//  Second approach:


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

var s1 = performance.now();;
sortedArray=myArray.sort(sortFunc)


var minBySortArray = sortedArray[0],
    maxBySortArray = sortedArray[myArray.length - 1]
    
var s2   = performance.now();;
 console.log("sort funciton took  " + (s2 - s1) + " milliseconds.");  
console.log("max ValBySortArray :"+max)
console.log("min Val BySortArray:"+min)

max = totalAVG.reduce(function (a, b) { return Math.max(a, b)}, -Infinity);

min = totalAVG.reduce(function (a, b) {return Math.min(a, b)}, Infinity);

또 하나, 케네벡의 대답과 비슷하지만 모두 한 줄로 늘어놓았습니다.

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

내장된 배열 개체를 사용하여 Math.max/Math.min을 대신 사용할 수 있습니다.

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

반응형