4

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.

3
  • tasks should be an array, not an object. Commented Aug 26, 2017 at 16:22
  • @NinaScholz why? would I still be able to access individual tasks using people[100].tasks[3].title if they were an array? Commented Aug 26, 2017 at 17:35
  • i was wondering, which data type you are using. the above is not a valid example. if you need properties, which reflects the taskID, then you need to use it in the example as well. Commented Aug 26, 2017 at 17:40

4 Answers 4

2

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

Sign up to request clarification or add additional context in comments.

3 Comments

Nice it works. Is there anyway you could provide some explanation to what you mean as functional dependent? I am actually just getting started with functional programming.
ownerName is functional dependent on ownerID when it is always true that given a value for ownerID, there can be only one value for ownerName associated with it, never two.
Nice, I like it.
1
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

Amazing. So simple. Thank you.
0

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

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.