I have an array of task objects and I want to transform these into a multidimensional object grouped by ownerID
var tasks = [
{taskID: "1", title: "task1", ownerID: "100", ownerName: "John", allocation: 80},
{taskID: "2", title: "task2", ownerID: "110", ownerName: "Sarah", allocation: 50},
{taskID: "3", title: "task3", ownerID: "110", ownerName: "Sarah", allocation: 50},
{taskID: "4", title: "task4", ownerID: "120", ownerName: "Mike", allocation: 25},
{taskID: "5", title: "task5", ownerID: "120", ownerName: "Mike", allocation: 45}];
This is my expected output:
var people = {
100: { ownerName: "John",
tasks: {
{taskID: "1", title: "task1", allocation: 80}
}
},
110: { ownerName: "Sarah",
tasks: {
{taskID: "2", title: "task2", allocation: 50}
{taskID: "3", title: "task3", allocation: 50}
}
},
120: { ownerName: "Mike",
tasks: {
{taskID: "4", title: "task4", allocation: 25}
{taskID: "5", title: "task5", allocation: 45}
}
},
};
I'm looping through the original data and assigning each row
people[ownerID] = {};
person = people[ownerID];
person['ownerName'] = ownerName;
person['tasks'] = {};
person[taskID] = {};
task = person[taskId];
task['taskID'] = taskID;
This seems to group by ownerID fine and creates a nested object of tasks but it will only add one task for each person.
Argh. Any help really appreciated.
4 Answers 4
Here is a functional way to do it (assuming ownerName is functional dependent on ownerID):
const tasks = [
{taskID: "1", title: "task1", ownerID: "100", ownerName: "John", allocation: 80},
{taskID: "2", title: "task2", ownerID: "110", ownerName: "Sarah", allocation: 50},
{taskID: "3", title: "task3", ownerID: "110", ownerName: "Sarah", allocation: 50},
{taskID: "4", title: "task4", ownerID: "120", ownerName: "Mike", allocation: 25},
{taskID: "5", title: "task5", ownerID: "120", ownerName: "Mike", allocation: 45}];
const result = tasks.reduce( (acc, {taskID, title, ownerID, ownerName, allocation }) => {
(acc[ownerID] = acc[ownerID] || { ownerName, tasks: [] })
.tasks.push( { taskID, title, allocation } );
return acc;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
3 Comments
people[ownerID] = {};
person['tasks'] = {};
These lines don't check if an object with the same key exists before and create a new object each time.
Try changing it to
people[ownerID] = people[ownerID] || {};
person['tasks'] = person['tasks'] || {};
1 Comment
Just one thing, the tasks should be an array, since objects can't hold another objects without having a key.
var tasks = [
{taskID: "1", title: "task1", ownerID: "100", ownerName: "John", allocation: 80},
{taskID: "2", title: "task2", ownerID: "110", ownerName: "Sarah", allocation: 50},
{taskID: "3", title: "task3", ownerID: "110", ownerName: "Sarah", allocation: 50},
{taskID: "4", title: "task4", ownerID: "120", ownerName: "Mike", allocation: 25},
{taskID: "5", title: "task5", ownerID: "120", ownerName: "Mike", allocation: 45}];
var transformed = tasks.reduce((obj, item)=> {
if(!obj[item.ownerID]) {
obj[item.ownerID] = {};
}
obj[item.ownerID].ownerName = item.ownerName;
if(!obj[item.ownerID].tasks) {
obj[item.ownerID].tasks = [];
}
obj[item.ownerID].tasks.push({taskID: item.taskID, title: item.title, allocation: item.allocation})
return obj;
}, {})
console.log(transformed);
Comments
You could use the logical OR as default operator ans assign a new object if the peroperty does not exists.
var tasks = [{ taskID: "1", title: "task1", ownerID: "100", ownerName: "John", allocation: 80 }, { taskID: "2", title: "task2", ownerID: "110", ownerName: "Sarah", allocation: 50 }, { taskID: "3", title: "task3", ownerID: "110", ownerName: "Sarah", allocation: 50 }, { taskID: "4", title: "task4", ownerID: "120", ownerName: "Mike", allocation: 25 }, { taskID: "5", title: "task5", ownerID: "120", ownerName: "Mike", allocation: 45 }],
people = {};
tasks.forEach(({ taskID, title, ownerID, ownerName, allocation }) => {
people[ownerID] = people[ownerID] || { ownerName, tasks: {} };
people[ownerID].tasks[taskID] = people[ownerID].tasks[taskID] || { taskID, title, allocation };
});
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }
tasksshould be an array, not an object.taskID, then you need to use it in the example as well.