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

时间:2012-01-14 18:38:49

标签: javascript arrays compare

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

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

我想专门针对“成本”,并获得最小值和最大值。我意识到我可以抓住成本值并将它们推送到javascript数组中,然后运行Fast JavaScript Max/Min

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

16 个答案:

答案 0 :(得分:121)

对于这样的东西,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.reduce(function(prev, curr){ 
        return prev[attrib] < curr[attrib] ? prev : curr; 
    });
 }

现在你可以说:

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

答案 1 :(得分:44)

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

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

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

答案 2 :(得分:21)

如果您不关心正在修改的数组,请使用sort

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

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

答案 3 :(得分:13)

我认为Rob W's answer真的是正确的(+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; }));

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

答案 4 :(得分:11)

使用+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize { CGSize actSize = image.size; float scale = actSize.width/actSize.height; if (scale < 1) { newSize.height = newSize.width/scale; } else { newSize.width = newSize.height*scale; } UIGraphicsBeginImageContext(newSize); [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } 功能,并使用Math

获取所需的值

这是jsbin:

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

map

更新:

如果您想使用ES6:

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

答案 5 :(得分:5)

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

答案 6 :(得分:2)

这是更好的解决方案

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

答案 7 :(得分:2)

使用Array.prototype.reduce(),您可以插入比较器函数来确定数组中的最小值,最大值等项。

&#13;
&#13;
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;
&#13;
&#13;
&#13;

答案 8 :(得分:2)

添加到Tristan Reid的答案(+使用es6),您可以创建一个接受回调的函数,该函数将包含您要应用于prev和{{1}的运算符}:

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

答案 9 :(得分:1)

这可以通过lodash的onChangeimport React, { Component } from "react"; import Select from "react-select"; export default class MultiSelect extends Component<*, State> { handleChange(option, action) { console.log(option, action); // return; if (action === "deselect-option") { action = "select-option"; // now how do I do the component's state? } } render() { return ( <Select isMulti className="basic-single" classNamePrefix="select" name="color" options={[{"label": "hello", "value": "hello"}, {"label": "world", "value": "world"}]} hideSelectedOptions={false} onChange={this.handleChange} /> ); } } 函数来实现。

Lodash的minBymaxBy文档

  

minBy

     

maxBy

     

这些方法接受一个iteratee,该iteratee会为其中的每个元素调用   数组以生成用于对值进行排名的条件。的   使用一个参数(值)调用iteratee。

解决方案

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

答案 10 :(得分:1)

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

答案 11 :(得分:1)

对于Max

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

分钟

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

答案 12 :(得分:0)

  

我们可以通过两种方法解决问题   上面已经介绍了这两种方法,但是缺少性能测试,因此请完成该操作

1,原生Java脚本方式
2,首先对对象排序然后很容易得到最小值    来自已排序obj的最大值

  

我还测试了两种牵引方式的性能

     

您还可以运行并测试性能...快乐编码(:

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

答案 13 :(得分:0)

对于一种简洁现代的解决方案,可以对数组执行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);

答案 14 :(得分:-2)

另一个,类似于肯纳贝克的回答,但都在一行中:

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

答案 15 :(得分:-2)

您可以使用内置的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