Reputation: 2731
I have an array like this -
"formats": [
{
"format": "eBook",
"published": "3/3/2014",
"id": "1234"
},
{
"format": "Paperback",
"published": "19/3/2020",
"id": "123"
},
{
"format": "eBook",
"published": "19/3/2020",
"id": "12345"
}]
and I would like to write a js filter function that should return me based on the latest format.So something like this
"formats": [
{
"format": "Paperback",
"published": "19/3/2020",
"id": "123"
},
{
"format": "eBook",
"published": "19/3/2020",
"id": "12345"
}]
Where object with id 1234 is removed because another object with the same format (eBook) has a greater published date.
I tried using JS's filter function, but somehow I am messing it up.
Upvotes: 0
Views: 113
Reputation: 1203
Here's my solution:
const formats = [
{
"format": "eBook",
"published": "3/3/2014",
"id": "1234"
},
{
"format": "Paperback",
"published": "19/3/2020",
"id": "123"
},
{
"format": "eBook",
"published": "19/3/2020",
"id": "12345"
}]
const getDateObj = (str) => new Date(str.split('/').map(i => i.length<2 ? `0${i}` : i).reverse().join('-'));
const getFilteredArrayOfLatestEntriesForFormats = (formatsArr) => {
const formatToLatestEntriesMap = formatsArr.reduce((latestFormatEntryMap,obj) => {
const publishedAt = getDateObj(obj.published);
if(!latestFormatEntryMap[obj.format] || latestFormatEntryMap[obj.format].publishedAt<publishedAt){
latestFormatEntryMap[obj.format] = {
...obj,
publishedAt: publishedAt
};
}
return latestFormatEntryMap;
},{})
return Object.keys(formatToLatestEntriesMap).map(format => {
delete formatToLatestEntriesMap[format].publishedAt;
return formatToLatestEntriesMap[format];
})
}
console.log(getFilteredArrayOfLatestEntriesForFormats(formats));
Upvotes: 0
Reputation: 5895
const formats = [
{
"format": "eBook",
"published": "3/3/2014",
"id": "1234"
},
{
"format": "Paperback",
"published": "27/3/2020",
"id": "123"
},
{
"format": "Paperback",
"published": "19/3/2020",
"id": "123"
},
{
"format": "eBook",
"published": "19/3/2020",
"id": "12345"
}];
function filterFormats(formats){
const toTime = (date) => new Date(date.replace(/(\d+)\/(\d+)\/(\d+)/, "$2/$1/$3")).getTime();
const data = formats.reduce((a, b) => {
if(b.format+'' in a && toTime(a[b.format].published) > toTime(b.published)) return a;
a[b.format] = b;
return a;
}, {});
return Object.values(data);
}
console.log(filterFormats(formats));
Upvotes: 2