0

I have this array of objects that goes like this

let data = [
    {
        "id": 1,
        "name": "Sam",
        "father": true,
        "group": "orange"
    },
    {
        "id": 2,
        "name": "Alex",
        "father": true,
        "group": "red"
    },
    {
        "id": 3,
        "name": "Rock",
        "father": true,
        "group": "blue"
    },
    {
        "id": 4,
        "name": "Liam",
        "father": false,
        "group": "red"
    },
    {
        "id": 5,
        "name": "Noah",
        "father": false,
        "group": "red"
    },
    {
        "id": 6,
        "name": "Oliver",
        "father": false,
        "group": "orange"
    },
    {
        "id": 7,
        "name": "Sara",
        "father": false,
        "group": "blue"
    },
    {
        "id": 8,
        "name": "Max",
        "father": false,
        "group": "red",

    }
]; 

And I want to sort it so every father has his children as a key called "member" which is an array of objects inside the father object. the children has to be the same color of his father's. so for example the output should be something like this :

     {
        "id": 1,
        "name": "Sam",
        "father": true,
        "group": "orange"
        "member":[
        {
            "id": 6,
            "name": "Oliver",
            "father": false,
            "group": "orange"
        }];


     {
            "id": 2,
            "name": "Alex",
            "father": true,
            "group": "red"
            "member":[
   {
        "id": 4,
        "name": "Liam",
        "father": false,
        "group": "red"
    },
    {
        "id": 5,
        "name": "Noah",
        "father": false,
        "group": "red"
    },
    {
        "id": 8,
        "name": "Max",
        "father": false,
        "group": "red",

    }
];

and so on .. I made it works but I used nested loops , this is my code :

function sorting(data) {
    //loop in all objects and find me all fathers
    data.forEach(fatherObjects => { 
        if (fatherObjects.father) {
            var member = [];
            //loop in all children objects and find me all children that has the same father color
            data.forEach(childrenObjects => {
                if (!childrenObjects.father && childrenObjects.group === fatherObjects.group) {
                    //add children objects to 'member' array
                    member.push(childrenObjects)
                }
            });
            //add 'member array vlaues to the member key inside father objects'
            fatherObjects["member"] = member;
            console.log(fatherObjects);
        }
    });
}
sorting(data);

This is working and all however this runs so slow because of the two nested loops How can I replace it with something more efficient and not so complex to understand.

6
  • "this runs so slow" have you actually measured the performance? JS in modern browsers can iterate a simple loop about a billion times per second, I suspect this code is not a bottleneck. Commented Jun 22, 2021 at 9:46
  • What denotes the father from the children? ie, if its just the group is it the first time an item is found which becomes the father? Commented Jun 22, 2021 at 9:48
  • @Jamiec . The father key has to be true and after that every object with the same father's group has to follow him . technically there is now way a child has more than one father and if you looked the data before sorting you notice that the fathers always comes first then the children , I tried to use these but I didn't figure it out. Commented Jun 22, 2021 at 9:52
  • @Teemu I didn't ; but I think there is a better way to use instead of looping the entire array 2 times every time . Commented Jun 22, 2021 at 9:52
  • You should race your horses, stackify.com/premature-optimization-evil Commented Jun 22, 2021 at 10:03

2 Answers 2

2

It can be done in a single loop using reduce to essentially group by the group property and Object.values to get the dessired result

const result = Object.values(data.reduce((acc, i) => {
  if (!acc[i.group]) {
    acc[i.group] = {
      ...i,
      member: []
    }
  } else {
    acc[i.group].member.push(i);
  }
  return acc;
}, {}));

Live example:

let data = [{
    "id": 1,
    "name": "Sam",
    "father": true,
    "group": "orange"
  },
  {
    "id": 2,
    "name": "Alex",
    "father": true,
    "group": "red"
  },
  {
    "id": 3,
    "name": "Rock",
    "father": true,
    "group": "blue"
  },
  {
    "id": 4,
    "name": "Liam",
    "father": false,
    "group": "red"
  },
  {
    "id": 5,
    "name": "Noah",
    "father": false,
    "group": "red"
  },
  {
    "id": 6,
    "name": "Oliver",
    "father": false,
    "group": "orange"
  },
  {
    "id": 7,
    "name": "Sara",
    "father": false,
    "group": "blue"
  },
  {
    "id": 8,
    "name": "Max",
    "father": false,
    "group": "red",

  }
];

const result = Object.values(data.reduce((acc, i) => {
  if (!acc[i.group]) {
    acc[i.group] = {
      ...i,
      member: []
    }
  } else {
    acc[i.group].member.push(i);
  }
  return acc;
}, {}));

console.log(result);

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

2 Comments

@MrXQ Im not sure it quite does what you're expecting though - I didnt notice that father attribute
@Jmaiec It did indeed . however I need some time to understand your solution the syntax looks wired to me , I'm new to JavaScript
1
function sorting(data) {
  var newFathersArray=[];
    data.forEach(fatherObjects => {
           if( fatherObjects.father ) {
             newFathersArray.push({
               ...fatherObjects,
               members:[]
             });
           }
    });
    data.forEach(fatherObject => {
       if( !fatherObject.father ) {
         newFathersArray.filter(f=>f.group===fatherObject.group)[0].members.push(fatherObject)
       }
    })

  return newFathersArray;
}
sorting(data);

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.