I have a JSON Data like this:
"Data": [
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
]
I want to merge two objects in this array, but it have same properties like date
, dow
at the end I want to represent data like this:
"Data": [
{
"time": "16:39:52",
"count": 18,
"date": "2019-01-16",
"dow": "Thursday"
"endTime": "19:41:03",
},
]
time
: should be least from both objects and endTime
should be largest of both of them
count
should be sum of both. date
and dow
is common in both objects
How can I merge these object in this way in node JS?
CodePudding user response:
const data=[
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
];
let date=(time)=>new Date().setHours(...time.split(":"));
let newData=[];
data.forEach((item)=>{
let findItem=newData.findIndex((e)=>e.date===item.date && e.dow===item.dow);
if(findItem!=-1){
let find=data.filter((e)=>e.dow===item.dow && e.date===item.date);
let time=find.filter((i)=>find.find(i2=>date(i2.time)>date(i.time)));
let endTime=find.filter((i)=>find.find(i2=>date(i2.endTime)<date(i.endTime)));
item.endTime=endTime?.[0]?.endTime || item?.endTime;
item.time=time?.[0]?.time || item?.time;
item.count=find.map((e)=>e.count).reduce((partialSum, a) => partialSum a, 0);
let findItem=newData.findIndex((e)=>e.date===item.date && e.dow===item.dow);
if(findItem!=-1) newData.splice(findItem,1);
newData.push(item);
}
else newData.push(item);
});
console.log(newData);
CodePudding user response:
Here's a simple and readable answer:
const data = [
{
time: "18:40:43",
count: 7,
endTime: "15:46:25",
date: "2019-01-16",
dow: "Thursday",
},
{
count: 11,
time: "16:39:52",
endTime: "19:41:03",
dow: "Thursday",
date: "2019-01-16",
},
];
const mergeObjects = (data) => {
mergedObj = { ...data[0] };
for (i = 1; i < data.length; i ) {
const obj = data[i];
for (const key in obj) {
switch (key) {
case "count":
mergedObj.count = (mergedObj.count || 0) obj.count;
case "time":
mergedObj.time =
mergedObj.time < obj.time ? mergeObjects.time : obj.time;
case "endTime":
mergedObj.endTime = mergedObj.endTime > obj.endTime ? mergeObjects.endTime : obj.endTime;
}
}
}
return mergedObj;
};
console.log(mergeObjects(data));
output
{
"time": "16:39:52",
"count": 18,
"date": "2019-01-16",
"dow": "Thursday"
"endTime": "19:41:03",
},
CodePudding user response:
Assuming
- "Data" would have only two objects inside it
- time would be in "HH::MM::SS" format
Pass the values onto constructJSON utility function which would return the formatted value
var Data = [
{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
]
function constructJSON(data)
{
const returnData = {}
returnData['count'] = data[0].count data[1].count
returnData['date'] = data[0].date // since its common for both
returnData['dow'] = data[0].dow // since its common for both
returnData['time'] = parseInt(data[0].time.split(':').join(''),10) < parseInt(data[1].time.split(':').join(''),10) ? data[0].time:data[1].time;
returnData['endTime'] = parseInt(data[0].endTime.split(':').join(''),10) > parseInt(data[1].endTime.split(':').join(''),10) ? data[0].endTime:data[1].endTime;
return returnData
}
console.log(constructJSON(Data))
CodePudding user response:
If you use Array.reduce, you should be able to do this pretty easily, it should also expand to let you expand with more than just 2 objects in the array.
const data = [{
"time": "18:40:43",
"count": 7,
"endTime": "15:46:25",
"date": "2019-01-16",
"dow": "Thursday"
},
{
"count": 11,
"time": "16:39:52",
"endTime": "19:41:03",
"dow": "Thursday",
"date": "2019-01-16"
},
];
//res will contain the output
const res = data.reduce(function(acc, curr) {
//Initially the accumulator will be null
if (!acc) return curr;
//Add the counts up
acc.count = curr.count;
//Convert both times into dates and find the minimum
const accTime = new Date(acc.date 'T' acc.time); //We add the T here since that's just how the Date constructor accepts times
const currTime = new Date(acc.date 'T' curr.time);
acc.time = new Date(Math.min(accTime, currTime)).toTimeString().split(' ')[0]; //See https://stackoverflow.com/questions/19346405/how-to-get-hhmmss-from-date-object
//Do the same for the end times but find the maximum
const accEndTime = new Date(acc.date 'T' acc.endTime);
const currEndTime = new Date(acc.date 'T' curr.endTime);
acc.endTime = new Date(Math.max(accEndTime, currEndTime)).toTimeString().split(' ')[0];
return acc;
});
console.log(res);
CodePudding user response:
Another way of merging - all keys are combined, the common keys are overwritten by the second object, but count
, time
and endTime
are calculated by special conditions
const
data = [{"time": "18:40:43","count": 7,"endTime": "15:46:25","date": "2019-01-16","dow": "Thursday"},{"count": 11,"time": "16:39:52","endTime": "19:41:03","dow": "Thursday","date": "2019-01-16"}],
[first, last] = data,
dumbDate = '2000-01-01 ',
result = {
...first,
...last,
count: first.count last.count,
time: (new Date(`${dumbDate}${first.time}`) < new Date(`${dumbDate}${last.time}`)) ? first.time : last.time,
endTime: (new Date(`${dumbDate}${first.endTime}`) > new Date(`${dumbDate}${last.endTime}`)) ? first.endTime : last.endTime,
};
console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}