Oliver
Oliver

Reputation: 1181

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.

Upvotes: 3

Views: 4741

Answers (6)

Sergei Ryzhov
Sergei Ryzhov

Reputation: 51

shortest way:

{...days.reduce((obj,d)=>({...obj,[d]:{ planned: 0, completed: 0 }}),{}), ...tasks}

Upvotes: 0

Nick Parsons
Nick Parsons

Reputation: 50684

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);

Upvotes: 1

Maheer Ali
Maheer Ali

Reputation: 36564

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)

Upvotes: 0

jo_va
jo_va

Reputation: 13964

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);

Upvotes: 5

0xc14m1z
0xc14m1z

Reputation: 3725

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)

Upvotes: 2

Alexandre Nicolas
Alexandre Nicolas

Reputation: 1949

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

Upvotes: 3

Related Questions