我有一个对象数组,我想比较特定对象属性上的这些对象。这是我的数组:
var myArray = [
{"ID": 1, "Cost": 200},
{"ID": 2, "Cost": 1000},
{"ID": 3, "Cost": 50},
{"ID": 4, "Cost": 500}
]
我想专门针对“成本”,并获得最小值和最大值。我意识到我可以抓住成本值并将它们推送到javascript数组中,然后运行Fast JavaScript Max/Min。
但是,通过绕过中间的数组步骤并直接关闭对象属性(在本例中为“Cost”),有更简单的方法吗?
答案 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.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);
答案 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(),您可以插入比较器函数来确定数组中的最小值,最大值等项。
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;
答案 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的onChange
和import 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的minBy
和maxBy
文档
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