1

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?

Debug Diva
  • 26,058
  • 13
  • 70
  • 123

6 Answers6

0

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);
Asad Haroon
  • 476
  • 3
  • 9
0

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",
},
Paolo Tormon
  • 312
  • 2
  • 11
  • If there is an object that doesn't have same propertied I don't want to merge with other objects, and put it in as a seperate object in the same array then what should I do? – santosh-kumar Mar 02 '22 at 07:18
  • 1
    @santosh-kumar In this case, please ask the question with actual input/output data without any ifs. – A1exandr Belan Mar 02 '22 at 07:48
0

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))
gcodess
  • 150
  • 5
0

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}
A1exandr Belan
  • 4,442
  • 3
  • 26
  • 48
0

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);
Arkin Solomon
  • 592
  • 1
  • 5
  • 23
0

Use Array#reduce() and Array#map() methods as follows:

const data = {"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 newD = {Data:data.Data.reduce(
    (prev,{date,dow,count,...r}) => 
        //check if an element in array prev has dow & date props equal to the current element
        prev.findIndex(p => p.date === date && p.dow === dow) > -1 ? 
            //If found process the matching element
            prev.map(({date:d,dow:w,count:c,...rs}) => 
                d === date && w === dow ? 
                ({...rs,date:d,dow:w,count:c+count,time:rs.time < r.time ? rs.time : r.time,endTime:rs.endTime > r.endTime ? rs.endTime : r.endTime}) : 
                ({...rs,date:d,dow:w,count:c})
            ) : 
            //If not add the current element to array prev
            prev.concat({...r,date,dow,count}), 
            //start off with an empty array
            []
)};

console.log( newD );
PeterKA
  • 24,158
  • 5
  • 26
  • 48