Reputation: 1289
I currently have any array of object literals which have the potential of coming in to the client-side with duplicate values (see the Date
key).
[
{
"Date": "2/26/2018",
"Title": "Story 1"
},
{
"Date": "2/27/2018",
"Title": "Story 2"
},
{
"Date": "2/27/2018",
"Title": "Story 3"
},
{
"Date": "2/28/2018",
"Title": "Story 4"
}
]
How could I check the value of the previous key to consolidate this in to 1 new object such as:
[
{
"Date": "2/26/2018",
"Title": "Story 1"
},
{
"Date": "2/27/2018",
"Stories": {
[
{
"Title": "Story 2"
},
{
"Title": "Story 3"
}
]
}
},
{
"Date": "2/28/2018",
"Title": "Story 4"
}
]
Here's the kicker - no frameworks such as Underscore.js can be used.
Thoughts?
Upvotes: 0
Views: 125
Reputation: 4488
Once you just want to create a Stories
object when it has titles
to be grouped I think this should work:
arr.reduce((acc, ele) => {
if(acc.length == 0) return acc.concat(ele);
var previous = acc[acc.length - 1];
if(ele.Date == previous.Date) {
if(!previous.Stories) previous.Stories = [{ title: previous.Title }];
previous.Stories.push({ title: ele.Title })
delete previous.Title;
return acc;
}
return acc.concat(ele);
}, [])
Upvotes: 0
Reputation: 17333
I think you need to break down the problem a bit more.
This is very similar to a GROUP BY
statement in SQL - essentially, you're grouping by Date
in this situation.
I would do it like so:
function parseStories(stories) {
// we're going to record previous stories in an object using their date, as that is the value we wish to group by
var previousStories = {};
stories.forEach(function (storyObj) {
// this is how we should insert the object - it fits the "shape" of object retrieval where there is more than 1 result
var insertObj = { Title: storyObj.Title };
if (previousStories[storyObj.Date]) {
// date already exists
previousStories[storyObj.Date].push(insertObj);
} else {
// new date
previousStories[storyObj.Date] = [insertObj];
}
});
// we generate the return result
var returnResult = [];
// NOTE - object property order is not guaranteed; however, you can mitigate this by using an array to sort the keys if you so wish
for (var key in previousStories) {
if (previousStories[key].length > 1) {
// if we have more than one story on a day, we can just add this to the Stories property
returnResult.push({
Date: key,
Stories: previousStories[key]
});
} else if (previousStories[key].length === 1) {
// if we only have one story, the structure of the return object changes slightly
returnResult.push({
Date: key,
Title: previousStories[key][0].Title
});
}
}
return returnResult;
}
There is quite a fair bit of logic involved in your grouping; where there is only a single element, the structure of the object you want produced changes subtly, from having a Stories
array to having a singular Title
property containing the title of that one story. Perhaps this design could be improved upon? It is generally easier to code upon a single data structure, as opposed to one that changes based on the plurality of its content.
Upvotes: 0
Reputation: 33726
You can use the function reduce
var array = [ { "Date": "2/26/2018", "Title": "Story 1" }, { "Date": "2/27/2018", "Title": "Story 2" }, { "Date": "2/27/2018", "Title": "Story 3" }, { "Date": "2/28/2018", "Title": "Story 4" }];
var result = Object.values(array.reduce((a, c) => {
if (a[c.Date]) {
a[c.Date].Stories.push({Title: c.Title});
} else {
a[c.Date] = { "Date": c.Date, "Stories": [{Title: c.Title}] };
}
return a;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2