Problem:
[
{ "id":5,
"name": "banana"
},
{ "id":5,
"name": "banana"
},
{ "id":4,
"name": "apple"
},
{ "id":1,
"name": "strawberry"
},
{ "id":1,
"name": "strawberry"
}
]
const arrayMap = new Map(Array.map(i => [i.id, {...i, amount: 0 }]));
Only have one method I’ve considered, such as mapping the array and assigning an amount per object using a loop but I’m not sure if this is a good way to do it, and the string part is still something I haven’t been able to figure out.
Order would be by highest ID number. The array could be seen as a shopping cart, you can have multiple bananas, and they’d just be listed under the same part of the string.
If you have 2 bananas with the ID 5, 1 apple with the ID 4, and 2 strawberries with the ID 1 it would display as such:
However, in my example the “banana” isn’t what makes it unique, it would be the ID. There would be no other bananas with different IDs, they would all be added with the same ID as duplicate objects.
"2x Banana, 1x Apple, 2x Strawberry"
Solution:
- Sort the array by ID, highest to lowest
- Reduce the sorted array to an object keyed by
id
withname
andcount
values. Name conflicts if any can be resolved by first-seen. - Map those entries to strings then join the whole thing together
const data = [{"id":5,"name":"banana"},{"id":5,"name":"banana"},{"id":4,"name":"apple"},{"id":1,"name":"strawberry"},{"id":1,"name":"strawberry"}];
const capitalise = (str) => str.replace(/\b[a-z]/g, (c) => c.toUpperCase());
const counts = data
.toSorted((a, b) => b.id - a.id) // sort by ID highest to lowest
.reduce((acc, { id, name }) => {
acc[id] ??= {
name,
count: 0,
};
acc[id].count++;
return acc;
}, {});
const str = Object.values(counts)
.map(({ name, count }) => `${count}x ${capitalise(name)}`)
.join(", ");
console.log(str);
If Array.prototype.toSorted() isn’t available, you can either
- Not care about altering the order of the original array and just use
Array.prototype.sort()
- Break the original array reference using either
[...data]
ordata.slice(0)
then use.sort()