ES6 reduce to new object

I have an array of all days of a year like so:

const days = ["2019-01-01", "2019-01-02", "2019-01-03" ...]

And I have an object holding planned and completed tasks for specific days:

const tasks = {"2019-01-01": {"planned": 3, "completed": 2,}, "2019-01-03": { "planned": 1, "completed": 0 }, "2019-01-10": { "planned": 1, "completed": 1} ... }

What I want is a new object that contains for all days information if tasks were planned and completed or not, like so:

const tasksNew = {"2019-01-01": {"planned": 3, "completed": 2}, "2019-02-02": {"planned": 0, "completed": 0} ...}

I know this somehow works with reduce but I can't help myself at the moment.

5 answers

  • answered 2019-02-10 12:26 Kornflexx

    const taskNew = days.reduce((acc, day) => {
      if (!tasks[day]) {
        return {
          ...acc,
          [day]: {
            planned: 0,
            completed: 0
          }
        }
      }  
      return {
        ...acc,
        [day]: tasks[day]
      } 
    }, {});
    

    for details about reduce: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/reduce

  • answered 2019-02-10 12:29 Nick Parsons

    You can use reduce to essentially map the days array to the keys in the tasks object. Here I loop through every day in days, check if it is in the tasks object. If it is I add the current day as the key and its associated object from tasks to the newTasks object. If the day isn't in the object, then I add the default complete: 0 and planned: 0 to the appended array:

    const days = ["2019-01-01", "2019-01-02", "2019-01-03"],
    tasks = {
      "2019-01-01": {
        "planned": 3,
        "completed": 2,
      },
      "2019-01-03": {
        "planned": 1,
        "completed": 0
      },
      "2019-01-10": {
        "planned": 1,
        "completed": 1
      }
    },
    
    newTasks = days.reduce((acc, day) => 
                       day in tasks ? 
                       {...acc, [day]: tasks[day]} : 
                       {...acc, [day]: {planned: 0, complete: 0}
                     }, {});
    
    console.log(newTasks);

  • answered 2019-02-10 12:29 0xc14m1z

    You can reduce your days array creating a new object. For each day, you'll check if there are a tasks for that day and merge them to your result map, if there are no tasks for that day, merge a default empty "indicator":

    const days = [
      "2019-01-01", 
      "2019-01-02", 
      "2019-01-03", 
      "2019-01-04",
      "2019-01-07",
      "2019-01-08",
      "2019-01-09",
      "2019-01-10"
    ]
    
    const DEFAULT = { "planned": 0, "completed": 0 } 
    
    const tasks = {
      "2019-01-01": {"planned": 3, "completed": 2,}, 
      "2019-01-03": { "planned": 1, "completed": 0 }, 
      "2019-01-10": { "planned": 1, "completed": 1 }
    }
    
    const result = days.reduce(
      (map, day) =>
        Object.assign({}, map, { [day]: tasks[day] ? tasks[day] : DEFAULT }),
      {}
    )
    
    console.log(result)

  • answered 2019-02-10 12:30 jo_va

    Use reduce on your days array. For each day, it an entry is found in your tasks object, add this entry to the accumulator, otherwise, return a default entry.

    Here is the MDN doc on Array.reduce().

    const days = ["2019-01-01", "2019-01-02", "2019-01-03"];
    const tasks = {"2019-01-01": {"planned": 3, "completed": 2,}, "2019-01-03": { "planned": 1, "completed": 0 }, "2019-01-10": { "planned": 1, "completed": 1} };
    
    const tasksNew = days.reduce((accum, day) => {
      accum[day] = tasks[day] ? tasks[day] : { planned: 0, completed: 0 };
      return accum;
    }, {});
    
    console.log(tasksNew);

  • answered 2019-02-10 12:36 Maheer Ali

    clone the tasks. Store keys of tasks in a variable. Then loop through days check if keys doesnot includes() day add it the the object newTasks

    const days = ["2019-01-01", "2019-01-02", "2019-01-03"]
    
    const tasks = {"2019-01-01": {"planned": 3, "completed": 2,}, "2019-01-03": { "planned": 1, "completed": 0 }, "2019-01-10": { "planned": 1, "completed": 1}}
    
    const newTasks = JSON.parse(JSON.stringify(tasks));
    
    const keys = Object.keys(tasks);
    days.forEach(day => {
      if(!keys.includes(day))
       newTasks[day] = {completed:0,planned:0} 
       }
    )
    console.log(newTasks)