In this problem I have a grocery list that I want to filter by removing duplicates and keeping only the duplicate with the higher count. Then also keeping items that are not duplicates. I ended up making this work through sheer programming by coincidence and would like to learn A better way to solve this problem. I commented my code below to share what's going on and my thought process. If anyone has a better way to solve this problem, I'd love to learn it.
在这个问题中,我有一个购物清单,我希望通过删除重复过滤并仅保留具有较高计数的副本来过滤。然后还保留不重复的项目。我最终通过巧合编程完成了这项工作,并希望学习更好的方法来解决这个问题。我评论下面的代码,分享正在发生的事情和我的思考过程。如果有人有更好的方法来解决这个问题,我很乐意学习它。
var groceryList = [
{
item: "Bananas",
count: 4
},
{
item: "Bananas",
count: 3
},
{
item: "Brussel Sprouts",
count: 2
},
{
item: "Bacon",
count: 100
},
{
item: "Beans",
count: 19
},
{
item: "Beans",
count: 5
}
]
const seen = {}
const newList = []
var removeDups = []
const list = groceryList.map(function(item) {
// if we haven't this item before (via check on item name) push it into seen object
// also push it to newList array
if (!seen[item.item]) {
seen[item.item] = item
newList.push(item)
}
// if we have seen the item during iteration...
else if (seen[item.item]) {
// remove it from the newList array
removeDups = newList.filter(function(listItem) {
if (listItem.item == item.item) {
console.log('matched');
} else {
return true
}
})
// and push in the item with the higher count
if (seen[item.item].count > item.count) {
removeDups.push(seen[item.item])
} else {
removeDups.push(item)
}
}
})
console.log(removeDups);
4 个解决方案
#1
2
You can use reduce
to concisely transform an array into another (or into an object) when the input items and output items aren't necessarily one-to-one:
当输入项和输出项不一定是一对一时,您可以使用reduce将数组简洁地转换为另一个(或转换为对象):
var groceryList=[{item:"Bananas",count:4},{item:"Bananas",count:3},{item:"Brussel Sprouts",count:2},{item:"Bacon",count:100},{item:"Beans",count:19},{item:"Beans",count:5}]
const filteredListObj = groceryList.reduce((a, { item, count }) => {
// this is a new item, or a duplicate with a greater quantity:
if (!a[item] || a[item].count < count) a[item] = { item, count };
return a;
}, {});
const filteredList = Object.values(filteredListObj);
console.log(filteredList);
#2
1
You could take a hash table and use the original objects without creating new ones.
您可以使用哈希表并使用原始对象而无需创建新对象。
var groceryList = [ { item: "Bananas", count: 3 }, { item: "Bananas", count: 4 }, { item: "Brussel Sprouts", count: 2 }, { item: "Bacon", count: 100 }, { item: "Beans", count: 19 }, { item: "Beans", count: 5 }],
hash = Object.create(null),
uniques = groceryList.reduce((r, o) => {
if (!(o.item in hash)) {
hash[o.item] = r.push(o) - 1;
}
if (r[hash[o.item]].count < o.count) {
r[hash[o.item]] = o;
}
return r;
}, []);
console.log(uniques);
.as-console-wrapper { max-height: 100% !important; top: 0; }
#3
0
You can create a map/object with name as key so that you will have unique items and override values if value is higher
您可以创建一个名称为键的地图/对象,这样您就可以拥有唯一的项目,如果值更高,则覆盖值
var groceryList = [
{
item: "Bananas",
count: 4
},
{
item: "Bananas",
count: 3
},
{
item: "Brussel Sprouts",
count: 2
},
{
item: "Bacon",
count: 100
},
{
item: "Beans",
count: 19
},
{
item: "Beans",
count: 5
}
];
let result = groceryList.reduce((map, obj) => {
if (!(obj.item in map) || (obj.item in map && map[obj.item] < obj.count)) {
map[obj.item] = obj.count;
}
return map;
}, {});
result = Object.keys(result).map(item => ({item , count: result[item]}));
console.log(result);
#4
0
Here's another answer, a little simpler perhaps. Basically using the fact that an object has unique keys and Math.max to pick the larger number of items.
这是另一个答案,也许更简单一些。基本上使用一个对象具有唯一键和Math.max来挑选更多项目的事实。
newList = [];
for(var i in groceryList){
let count = newList[groceryList[i].item] || 0;
newList[groceryList[i].item] = Math.max(groceryList[i].count, count);
};
console.log(newList);
Fiddle: https://jsfiddle.net/w2szmmya/
#1
2
You can use reduce
to concisely transform an array into another (or into an object) when the input items and output items aren't necessarily one-to-one:
当输入项和输出项不一定是一对一时,您可以使用reduce将数组简洁地转换为另一个(或转换为对象):
var groceryList=[{item:"Bananas",count:4},{item:"Bananas",count:3},{item:"Brussel Sprouts",count:2},{item:"Bacon",count:100},{item:"Beans",count:19},{item:"Beans",count:5}]
const filteredListObj = groceryList.reduce((a, { item, count }) => {
// this is a new item, or a duplicate with a greater quantity:
if (!a[item] || a[item].count < count) a[item] = { item, count };
return a;
}, {});
const filteredList = Object.values(filteredListObj);
console.log(filteredList);
#2
1
You could take a hash table and use the original objects without creating new ones.
您可以使用哈希表并使用原始对象而无需创建新对象。
var groceryList = [ { item: "Bananas", count: 3 }, { item: "Bananas", count: 4 }, { item: "Brussel Sprouts", count: 2 }, { item: "Bacon", count: 100 }, { item: "Beans", count: 19 }, { item: "Beans", count: 5 }],
hash = Object.create(null),
uniques = groceryList.reduce((r, o) => {
if (!(o.item in hash)) {
hash[o.item] = r.push(o) - 1;
}
if (r[hash[o.item]].count < o.count) {
r[hash[o.item]] = o;
}
return r;
}, []);
console.log(uniques);
.as-console-wrapper { max-height: 100% !important; top: 0; }
#3
0
You can create a map/object with name as key so that you will have unique items and override values if value is higher
您可以创建一个名称为键的地图/对象,这样您就可以拥有唯一的项目,如果值更高,则覆盖值
var groceryList = [
{
item: "Bananas",
count: 4
},
{
item: "Bananas",
count: 3
},
{
item: "Brussel Sprouts",
count: 2
},
{
item: "Bacon",
count: 100
},
{
item: "Beans",
count: 19
},
{
item: "Beans",
count: 5
}
];
let result = groceryList.reduce((map, obj) => {
if (!(obj.item in map) || (obj.item in map && map[obj.item] < obj.count)) {
map[obj.item] = obj.count;
}
return map;
}, {});
result = Object.keys(result).map(item => ({item , count: result[item]}));
console.log(result);
#4
0
Here's another answer, a little simpler perhaps. Basically using the fact that an object has unique keys and Math.max to pick the larger number of items.
这是另一个答案,也许更简单一些。基本上使用一个对象具有唯一键和Math.max来挑选更多项目的事实。
newList = [];
for(var i in groceryList){
let count = newList[groceryList[i].item] || 0;
newList[groceryList[i].item] = Math.max(groceryList[i].count, count);
};
console.log(newList);
Fiddle: https://jsfiddle.net/w2szmmya/