簡體   English   中英

比較 JavaScript 對象數組以獲得最小值/最大值

[英]Compare JavaScript Array of Objects to Get Min / Max

我有一個對象數組,我想比較特定 object 屬性上的這些對象。 這是我的數組:

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

我想專門將“成本”歸零,並獲得最小值和最大值。 我意識到我可以獲取成本值並將它們推入 javascript 數組,然后運行Fast JavaScript Max/Min

但是,是否有一種更簡單的方法可以繞過中間的數組步驟並直接關閉對象屬性(在本例中為“Cost”)?

reduce 適合這樣的事情:在對象數組上執行聚合操作(如 min、max、avg 等),並返回單個結果:

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

一種方法是遍歷所有元素並將其與最高/最低值進行比較。

(創建一個數組,調用數組方法對於這個簡單的操作來說太過分了)。

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

如果您不關心正在修改的數組,請使用sort

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

我認為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.minMath.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);

嘗試( a是數組, 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'));

最大

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

分鍾

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

使用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;

這可以通過 lodash 的minBymaxBy函數來實現。

Lodash 的minBymaxBy文檔

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

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

這些方法接受一個 iteratee,它為數組中的每個元素調用以生成對值進行排名的標准。 迭代器使用一個參數調用:(值)。

解決方案

 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>

這是更好的解決方案

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

添加到 Tristan Reid 的答案(+ 使用 es6),您可以創建一個接受回調的函數,該函數將包含要應用於prevcurr的運算符:

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

對於簡潔、現代的解決方案,可以對數組執行reduce操作,跟蹤當前的最小值和最大值,因此數組只迭代一次(這是最佳的)。

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

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

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

我們可以通過兩種方法解決問題 上面已經解釋了這兩種方法,但是缺少性能測試,所以完成了那個

1、原生java-script方式
2、首先對對象進行排序,然后很容易從排序后的對象中得到最小值最大值

我還測試了兩種方法的性能

您還可以運行和測試性能...快樂編碼(:

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

另一個,類似於 Kennebec 的回答,但都在一行中:

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

您可以使用內置 Array 對象來使用 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM