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

时间:2021-07-28 02:55:19

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数组中,然后运行快速的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?

但是,是否有一种更简单的方法,绕过中间的数组步骤,直接离开对象属性(在本例中为“Cost”)?

10 个解决方案

#1


37  

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

#2


86  

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

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

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

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

Now you can just say:

现在你可以说:

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

#3


18  

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]

#4


12  

I think Rob W's answer is really the right one (+1), but just for fun: if you wanted to be "clever", you could do 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.

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

#5


9  

Use Math functions and pluck out the values you want with map.

使用数学函数,把你想要的值取下来。

Here is the jsbin:

这是jsbin:

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

https://jsbin.com/necosu/1/edit?js,控制台

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

#6


2  

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;

#7


1  

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

#8


1  

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:

加入Tristan Reid的答案(+使用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

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

#9


-1  

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; 

#10


-2  

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

可以使用内置数组对象来使用Math.max/Math。最小值:

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

#1


37  

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

#2


86  

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

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

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

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

Now you can just say:

现在你可以说:

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

#3


18  

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]

#4


12  

I think Rob W's answer is really the right one (+1), but just for fun: if you wanted to be "clever", you could do 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.

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

#5


9  

Use Math functions and pluck out the values you want with map.

使用数学函数,把你想要的值取下来。

Here is the jsbin:

这是jsbin:

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

https://jsbin.com/necosu/1/edit?js,控制台

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

#6


2  

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;

#7


1  

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

#8


1  

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:

加入Tristan Reid的答案(+使用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

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

#9


-1  

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; 

#10


-2  

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

可以使用内置数组对象来使用Math.max/Math。最小值:

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