0

I have an array in Javascript and I need to combine objects if they have equal reminder.date

const tasks = [
{
 id: 1,
 title: "call Tom",
 reminders: {
  date: "2022-02-01",
  time: "09:30"
 }
},
{
 id: 2,
 title: "Meet Bred",
 reminders: {
  date: "2022-02-01",
  time: "10:30"
 }
},
{
 id: 3,
 title: "Mail Susan",
 reminders: {
  date: "2022-03-01",
  time: "19:00"
 }
},

Output should be like this

const combinedTasks = [
{
 id: 1,
 tasks: ["call Tom", "Meet Bred"],
 reminders: {
  date: "2022-02-01",
  time: "09:30"
 }
},
{
 id: 3,
 tasks: ["Mail Susan"]
 reminders: {
  date: "2022-03-01",
  time: "19:00"
 }
}

I suppose that I need to use Array.reduce method but I dont have idea hot to do it correctly

4 Answers4

2

Here is one way you can accomplish this using reduce()

let tasks = [{
    id: 1,
    title: "call Tom",
    reminders: {
        date: "2022-02-01",
        time: "09:30"
    }
}, {
    id: 2,
    title: "Meet Bred",
    reminders: {
        date: "2022-02-01",
        time: "10:30"
    }
}, {
    id: 3,
    title: "Mail Susan",
    reminders: {
        date: "2022-03-01",
        time: "19:00"
    }
}];

let combinedTasks = tasks.reduce((combined, x) => {
    // Try to find an existing item in the combined tasks array where the date equals this task item.
    let match = combined.find(y => y.reminders.date == x.reminders.date);
    if (match) {
        // If we find a match, add this task item's title to the combined item's tasks array.
        match.tasks.push(x.title);
    } else {
        // If we didn't find a match, take this task item and turn it into a combined tasks item with a tasks array so that future items in the tasks array can be combined with this one.
        let copy = { ...x };
        copy.tasks = [x.title];
        delete copy.title;
        combined.push(copy);
    }
    return combined;
}, []);


console.log(combinedTasks);
elyonis
  • 36
  • 2
  • My answer was really close to yours so just kept my comments here, Can you please add a working version as well? Your code looks great and should work well :) – Tushar Gupta Feb 22 '22 at 14:22
  • Thanks! I've changed my example above to be a snippet. – elyonis Feb 22 '22 at 14:38
1
const tasks = [
{
 id: 1,
 title: "call Tom",
 reminders: {
  date: "2022-02-01",
  time: "09:30"
 }
},
{
 id: 2,
 title: "Meet Bred",
 reminders: {
  date: "2022-02-01",
  time: "10:30"
 }
},
{
 id: 3,
 title: "Mail Susan",
 reminders: {
  date: "2022-03-01",
  time: "19:00"
 }
}
]
tasks.sort((a,b)=>{
  return new Date(a.reminders.date) - new Date(b.reminders.date)
})

let output = [];
tasks.map((val,index)=>{
   if(index===0){
      let obj = {}
      temp = [];
      temp.push(val.title);
      obj.id = val.id;
      obj.tasks = [...temp];
      obj.reminders = {...val.reminders};
      output.push(obj);
   }else{
      if(output[output.length-1].reminders.date===val.reminders.date){
         output[output.length-1].tasks.push(val.title);
      }else{
          let obj = {}
          temp = [];
          temp.push(val.title);
          obj.id = val.id;
          obj.tasks = [...temp];
          obj.reminders = val.reminders;
          output.push(obj);
      }
   }
})

Try this solution , it works .

Output : 
[
  {
    id: 1,
    tasks: [ 'call Tom', 'Meet Bred' ],
    reminders: { date: '2022-02-01', time: '09:30' }
  },
  {
    id: 3,
    tasks: [ 'Mail Susan' ],
    reminders: { date: '2022-03-01', time: '19:00' }
  }
]

Output of this code is as expected . I hope this is helpful .

Hritik Sharma
  • 1,756
  • 7
  • 24
  • `tasks.sort((a,b)=>{ return new Date(a.reminders.date) - new Date(b.reminders.date) })` thank for sharing your solution but I did not understand what is for ? – Ruslan Almukhanov Feb 22 '22 at 14:21
  • This basically sorts with respect to date ... what if your array is of large size and same date objects are not beside each other , so this sort function would be helpful in that case . – Hritik Sharma Feb 22 '22 at 14:23
1

you are right, you have to use the reduce method.

Use it to loop over your initial array. So for each task, you can watch in your futur array if you have a task at the current task date. Else you can create a new task and add next tasks later.

const tasks = [
    {
        id: 1,
        title: "call Tom",
        reminders: {
            date: "2022-02-01",
            time: "09:30"
        }
    },
    {
        id: 2,
        title: "Meet Bred",
        reminders: {
            date: "2022-02-01",
            time: "10:30"
        }
    },
    {
        id: 3,
        title: "Mail Susan",
        reminders: {
            date: "2022-03-01",
            time: "19:00"
        }
    }
];

const combinatedTasks = tasks.reduce((_combinatedTasks, currentTask) => {
    const currentDate = currentTask.reminders.date;
    const combinatedTaskAtCurrentDate = _combinatedTasks.find(task => task.reminders.date === currentDate);
    if (combinatedTaskAtCurrentDate) {
        combinatedTaskAtCurrentDate.tasks.push(currentTask.title);
    } else {
        _combinatedTasks.push({
            id: currentTask.id,
            tasks: [currentTask.title],
            reminders: currentTask.reminders
        });
    }
    return _combinatedTasks;
}, []);

console.log(combinatedTasks);

Maxime Chevallier
  • 277
  • 1
  • 4
  • 14
0

I hope this approach would help you.

const tasks = [
{
 id: 1,
 title: "call Tom",
 reminders: {
  date: "2022-02-01",
  time: "09:30"
 }
},
{
 id: 2,
 title: "Meet Bred",
 reminders: {
  date: "2022-02-01",
  time: "10:30"
 }
},
{
 id: 3,
 title: "Mail Susan",
 reminders: {
  date: "2022-03-01",
  time: "19:00"
 }
}];

let cmbArray =[];
tasks.forEach(x=>{
  if ( item = cmbArray.find(a=>a.reminders.date === x.reminders.date))  
  {
    item.tasks.push(x.title);    
  }
  else
  {
   x.tasks = [x.title];
   delete  x.title;
   cmbArray.push(x);
   }
});

  console.log(cmbArray);
D A
  • 1,724
  • 1
  • 8
  • 19