简体   繁体   English

比较对象的JavaScript数组以同时获得具有2个属性的最小值/最大值

[英]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 你可以做这样的事情

  • Randomize array 随机数组
  • Loop through randomized array, use object to hold max and min value 遍历随机数组,使用对象保存最大值和最小值
  • If the value is not available on min and max initialize with current value 如果minmax不可用,请使用当前值初始化
  • Check if the price is less than or equal to min value, if it is equal and count is same keep the previous one else update with new value 检查价格是否小于或等于最小值,如果价格相等且计数相同,则将其他价格更新为新值
  • In same way check for greater or equal than max value and update accordingly 以相同的方式检查是否大于或等于最大值并相应地更新

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM