比较 JavaScript 对象数组以获取最小值/最大值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8864430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:50:45  来源:igfitidea点击:

Compare JavaScript Array of Objects to Get Min / Max

javascriptarrayscompare

提问by firedrawndagger

I have an array of objects and I want to compare those objects on a specific object property. Here's my array:

我有一个对象数组,我想在特定对象属性上比较这些对象。这是我的数组:

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

I'd like to zero in on the "cost" specifically and a get a min and maximum value. I realize I can just grab the cost values and push them off into a javascript array and then run the Fast JavaScript Max/Min.

我想特别将“成本”归零并获得最小值和最大值。我意识到我可以只获取成本值并将它们推送到一个 javascript 数组中,然后运行Fast JavaScript Max/Min

However is there an easier way to do this by bypassing the array step in the middle and going off the objects properties (in this case "Cost") directly?

但是,是否有一种更简单的方法可以通过绕过中间的数组步骤并直接关闭对象属性(在本例中为“成本”)?

采纳答案by Rob W

The fastest way, in this case, is looping through all elements, and compare it to the highest/lowest value, so far.

在这种情况下,最快的方法是循环遍历所有元素,并将其与迄今为止的最高/最低值进行比较。

(Creating an array, invoking array methods is overkill for this simple operation).

(创建一个数组,调用数组方法对于这个简单的操作来说太过分了)。

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

回答by Tristan Reid

The reduce is good for stuff like this: to perform aggregate operations (like min, max, avg, etc.) on an array of objects, and return a single result:

reduce 适合这样的事情:在对象数组上执行聚合操作(如 min、max、avg 等),并返回单个结果:

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

...or you can define that inner function with ES6 function syntax:

...或者您可以使用 ES6 函数语法定义该内部函数:

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

If you want to be cute you can attach this to array:

如果你想变得可爱,你可以把它附加到数组:

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

Now you can just say:

现在你可以说:

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

Please note that if you intend to use this, it doesn't have full checks for every situation. If you pass in an array of primitive types, it will fail. If you check for a property that doesn't exist, or if not all the objects contain that property, you will get the last element. This version is a little more bulky, but has those checks:

请注意,如果您打算使用它,它不会对每种情况进行全面检查。如果传入基本类型数组,它将失败。如果您检查不存在的属性,或者不是所有对象都包含该属性,您将获得最后一个元素。这个版本有点笨重,但有这些检查:

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

回答by katspaugh

Use sort, if you don't care about the array being modified.

使用sort,如果你不关心的阵列进行修改。

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

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

回答by Rupert

Use Mathfunctions and pluck out the values you want with map.

使用Math函数并用 提取出你想要的值map

Here is the jsbin:

这是jsbin:

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

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

UPDATE:

更新:

If you want to use ES6:

如果你想使用 ES6:

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

回答by J. Holmes

I think Rob W's answeris really the right one (+1), but just for fun: if you wanted to be "clever", you coulddo something like this:

我认为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"));

or if you had a deeply nested structure, you could get a little more functional and do the following:

或者如果你有一个深层嵌套的结构,你可以得到更多的功能并执行以下操作:

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

These could easily be curried into more useful/specific forms.

这些可以很容易地变成更有用/特定的形式。

回答by Issa Lafi

for Max

最大

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

for min

分钟

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

回答by Mr. Polywhirl

Using Array.prototype.reduce(), you can plug in comparator functions to determine the min, max, etc. item in an array.

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

回答by James Moran

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 prevand curr:

添加到 Tristan Reid 的答案(+ 使用 es6),您可以创建一个接受回调的函数,该函数将包含要应用于prevand的运算符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);

回答by Deepak Sisodiya

This is more better solution

这是更好的解决方案

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

回答by Kamil Kie?czewski

Try (ais array, fis field to compare)

尝试(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'));