[英]Compare JavaScript Array of Objects to Get Min / Max With 2 Properties At the Same Time
var items = [
{"ID": 1, "Cost": 200, "Count": 4},
{"ID": 2, "Cost": 1000, "Count": 2},
{"ID": 3, "Cost": 50, "Count": 10},
{"ID": 4, "Cost": 50, "Count": 10},
{"ID": 5, "Cost": 50, "Count": 10},
{"ID": 6, "Cost": 50, "Count": 8}
]
I want to get the lowest Cost item, and if many of them are the same cost, I want to get the one with the highest count, and if there are still multiple, I want to get a random item. 我想获得成本最低的项目,如果其中许多成本相同,我想获得计数最高的项目,如果还有多个,我希望获得一个随机项目。
var lowestCost = items.reduce(function(prev, curr) {
return prev.Cost < curr.Cost ? prev : curr;
});
This is the way to get the lowest cost, any simple way to do the other comparisons simultaneously? 这是获得最低成本的方法,同时进行其他比较的任何简单方法是吗?
A not so-random solution : 一个不太随机的解决方案:
const items = [ {"ID": 1, "Cost": 200, "Count": 4}, {"ID": 2, "Cost": 1000, "Count": 2}, {"ID": 3, "Cost": 50, "Count": 10}, {"ID": 4, "Cost": 50, "Count": 10}, {"ID": 5, "Cost": 50, "Count": 10}, {"ID": 6, "Cost": 50, "Count": 8} ]; const computeLowestCost = () => { return items.reduce(function(prev, curr) { const isEqualPriceAndCount = (prev.Cost === curr.Cost) && (prev.Count === curr.Count); if (isEqualPriceAndCount) { // return a random item if price and count are the same return (!!Math.round(Math.random())) ? prev : curr; } return !!((prev.Cost < curr.Cost) || (prev.Count > curr.Count)) ? prev : curr; }); } const lowestCost = computeLowestCost(); console.log(lowestCost); // Randomness...is not that random because // 1st item has 1/2 * 1/2 * 1/2 chance to remain // 2nd item has 1/2 * 1/2 chance to remain // 3rd item has 1/2 chance to remain const results = {}; for (let i = 0; i < 1000000;i++) { const res = computeLowestCost(); results[res.ID]= !!results[res.ID] ? ++results[res.ID] : 1; } console.log(results)
A more random solution : 更加随机的解决方案:
const items = [ {"ID": 1, "Cost": 200, "Count": 4}, {"ID": 2, "Cost": 1000, "Count": 2}, {"ID": 3, "Cost": 50, "Count": 10}, {"ID": 4, "Cost": 50, "Count": 10}, {"ID": 5, "Cost": 50, "Count": 10}, {"ID": 6, "Cost": 50, "Count": 8} ]; const shuffle = (array) => array.sort(() => Math.random() - 0.5); const computeLowestCost = () => { shuffle(items); return items.reduce(function(prev, curr) { const isEqualPriceAndCount = (prev.Cost === curr.Cost) && (prev.Count === curr.Count); if (isEqualPriceAndCount) { // return a random item if price and count are the same return (!!Math.round(Math.random())) ? prev : curr; } return !!((prev.Cost < curr.Cost) || (prev.Count > curr.Count)) ? prev : curr; }); } const lowestCost = computeLowestCost(); console.log(lowestCost); // Randomness...almost equally distributed const results = {}; for (let i = 0; i < 1000000;i++) { const res = computeLowestCost(); results[res.ID]= !!results[res.ID] ? ++results[res.ID] : 1; } console.log(results) // For more randomness we could shuffle the array initially
You could get an array of the reduced data set and then take a random object. 您可以获取缩减数据集的数组,然后获取一个随机对象。
var items = [{ ID: 1, Cost: 200, Count: 4 }, { ID: 2, Cost: 1000, Count: 2 }, { ID: 3, Cost: 50, Count: 10 }, { ID: 4, Cost: 50, Count: 10 }, { ID: 5, Cost: 50, Count: 10 }, { ID: 6, Cost: 50, Count: 8 }], result = items.reduce((r, o) => { if (!r || r[0].Cost > o.Cost || r[0].Cost === o.Cost && r[0].Count < o.Count) { return [o]; } if (r[0].Cost === o.Cost && r[0].Count === o.Count) { r.push(o); } return r; }, null); console.log(result[Math.floor(Math.random() * result.length)]); // random console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
So a not so simple way would be to just do another ternary right afterwards to figure out if it was equal to or greater than. 因此,不是那么简单的方法是只在事后再执行另一个三元运算来确定它是否等于或大于。 And then we would have another ternary to figure out which one has the higher count etc...
然后,我们将有另一个三元数来找出哪个具有更高的计数等等。
var items = [
{"ID": 1, "Cost": 200, "Count": 4},
{"ID": 2, "Cost": 1000, "Count": 2},
{"ID": 3, "Cost": 50, "Count": 10},
{"ID": 4, "Cost": 50, "Count": 10},
{"ID": 5, "Cost": 50, "Count": 10},
{"ID": 6, "Cost": 50, "Count": 8}
]
var lowestCost = items.reduce(function(prev, curr) {
return prev.Cost < curr.Cost ? prev: (prev.Cost == curr.Cost ? (prev.Count > curr.Count ? prev: curr) : curr);
});
Create an array to contain costs and create an array to contain count. 创建一个包含成本的数组,并创建一个包含计数的数组。 Pick out the min value from cost and max value from the count.
从成本中选择最小值,从计数中选择最大值。 Filter the array and compare them.
过滤数组并进行比较。 The code is self-explanatory.
该代码是不言自明的。 Comments for further explanation
评论以进一步解释
var items = [ {"ID": 1, "Cost": 200, "Count": 4}, {"ID": 2, "Cost": 1000, "Count": 2}, {"ID": 3, "Cost": 50, "Count": 10}, {"ID": 4, "Cost": 50, "Count": 10}, {"ID": 5, "Cost": 50, "Count": 10}, {"ID": 6, "Cost": 50, "Count": 8} ] let costs = items.map(objs => Number(objs["Cost"])) // get all the costs from the items let counts = items.map(objs => Number(objs["Count"])) //.. get all the counts from the items let mincost = Math.min(...costs) // get the mininum cost let maxcount = Math.max(...counts) // get the max cost let answer = items.filter((objs) => { // filter the items array if (objs["Cost"] == mincost){ // if the cost is minimum if (objs["Count"] == maxcount) { // if the count is maximum return objs // return the object } } }) if (answer.length >= 1) { // if more than one answers let random = answer[Math.floor(Math.random() * answer.length)]; // return a random value console.log(random); }else{ console.log(answer) // else just log the value }
Math.floor(Math.random() * answer.length)
this gives you a random number in the range of the length of the array. Math.floor(Math.random() * answer.length)
这为您提供了一个在数组长度范围内的随机数。 So you can just plug it into the array's selector. 因此,您只需将其插入数组的选择器即可。
This translates to 这转化为
var items = [{"ID": 1, "Cost": 200, "Count": 4},{"ID": 2, "Cost": 1000, "Count": 2},{"ID": 3, "Cost": 50, "Count": 10},{"ID": 4, "Cost": 50, "Count": 10},{"ID": 5, "Cost": 50, "Count": 10},{"ID": 6, "Cost": 50, "Count": 8}] let mincost = Math.min(...items.map(objs => Number(objs["Cost"]))) let maxcount = Math.max(...items.map(objs => Number(objs["Count"]))) let answer = items.filter(objs => objs["Cost"] == mincost && objs["Count"] == maxcount) if (answer.length >= 1) { let random = answer[Math.floor(Math.random() * answer.length)]; console.log(random); }else{ console.log(answer) }
You can do something like this 你可以做这样的事情
min
and max
initialize with current value min
和max
不可用,请使用当前值初始化 var items = [ {"ID": 1, "Cost": 200, "Count": 4}, {"ID": 2, "Cost": 1000, "Count": 2}, {"ID": 3, "Cost": 50, "Count": 10}, {"ID": 4, "Cost": 50, "Count": 10}, {"ID": 5, "Cost": 50, "Count": 10}, {"ID": 6, "Cost": 50, "Count": 8} ] let randomizeArray = _.shuffle(items) let op = randomizeArray.reduce((op,inp)=>{ op.max = op.max || inp op.min = op.min || inp if(inp.Cost <= op.min.Cost){ if((op.min.Cost > inp.Cost) || (op.min.Count < inp.Count)){ op.min = inp } } if(inp.Cost >= op.max.Cost){ if((op.max.Cost < inp.Cost) || (op.max.Count < inp.Count)){ op.max = inp } } return op },{}) console.log(op)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>
items = items.sort((a,b) => a.Cost < b.Cost ? -1 : (a.Cost == b.Cost ? 0 : 1))
items = items.filter(item => item.Count == items[0].Count)
return items.length != 0 ? items[0] : null
This will do it 这会做到的
prev.Cost === curr.Cost && prev.Count > curr.Count || prev.Cost < curr.Cost
? prev
: curr
Or maybe more clever: 或者更聪明:
((prev.Cost - curr.Cost) || (prev.Count - curr.Count)) < 0
? curr
: prev
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.