find duplicate obj properties and return lowest count property

Multi tool use
find duplicate obj properties and return lowest count property
Lets say I had an array that looked like:
[
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1}
{count: 10, category: 8},
...
]
What I want is to find the lowest count from each category and return a new array of objects. I could easily do this using a plain old loop i think, but would like to use map().reduce or some other new func technique.
4 Answers
4
There are many ways to do it. One would be:
function filterLowestCounts(a) {
const lowestCountsByCategory = a.reduce(
(result, { count, category }) => ({
...result,
[category]: Math.min(count, result[category] || Number.MAX_SAFE_INTEGER)
}),
{}
)
return Object.entries(lowestCountsByCategory).map(
([category, count]) => ({ count, category: Number(category) })
)
}
Call it like this:
filterLowestCounts([
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1},
{count: 10, category: 8},
])
Result:
[
{count: 7, category: 1},
{count: 3, category: 2},
{count: 1, category: 4},
{count: 5, category: 8},
]
It looks a little bit messy but this would be an approach to do it in one line using concatenation and nesting of array functions filter, map and reduce:
let array = [
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1},
{count: 10, category: 8}
]
let result = array.filter((value, index, self)=>{
return self.findIndex((innerValue)=>{
return innerValue.category == value.category}) === index;
}).map((item)=>{
return { count: array.filter((innerItem)=>{
return innerItem.category == item.category
}).reduce((min, item)=>{
return (item.count < min) ? item.count : min; }).count, category: item.category};
});
console.log(result);
Using Array#reduce()
to create object with categories as keys and objects as values then get array using Object#values()
Array#reduce()
Object#values()
const res= Object.values(
data.reduce((acc, {count, category}) => {
const o = acc[category] || (acc[category] = {count, category});
o.count = Math.min(o.count, count);
return acc;
},{})
);
console.log(JSON.stringify(res))
<script>
var data= [
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1},
{count: 10, category: 8}
]
</script>
var list = [
{count: 1, category: 4},
{count: 2, category: 4},
{count: 3, category: 2},
{count: 4, category: 2},
{count: 5, category: 8},
{count: 6, category: 8},
{count: 7, category: 1},
{count: 8, category: 1},
{count: 9, category: 1},
{count: 10, category: 8}
];
function groupAndGetMin(list, keyGetter, valueGetter) {
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
const value = valueGetter(item);
const o = map.get(key);
if (!o) {
map.set(key, item.count);
} else {
map.set(key, Math.min(o, value));
}
});
return map;
}
var result = groupAndGetMin(list, l => l.category, i => i.count);
// this will return Map(4) {4 => 1, 2 => 3, 8 => 5, 1 => 7}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
This should help stackoverflow.com/q/14446511/831878
– Ray Toal
Jul 2 at 0:07