1

I have a javascript array of objects, where there is a property with another array as value, as seen here:

var data = [
{
id: 1,
parent: [1,2,3,4]
}, 
{
id: 2,
parent: [5,6,7,8]
}
]

I am trying to split it, so every object with more than one parent, gets a duplicated copy of itself, each copy with a different parent. I have done this so far:

var updateddata = JSON.parse(JSON.stringify(data));

for (var i = 0; i < updateddata[i].parent.length; i++) {
    while (updateddata[i].parent.length > 1) {
        updateddata.push({
        id: updateddata[i].id,
        parent: updateddata[i].parent[0]
    })
updateddata[i].parent.shift()
}
}

And it works perfect, except for the fact that when doing console.log(JSON.stringify(updateddata)) I can see that the first two entries have as a parent an array with one single entry, unlike the others, which are already outside the array:

This is the console.log for updateddata:

[
{"id":1,"parent":[4]},
{"id":2,"parent":[8]},
{"id":1,"parent":1},
{"id":1,"parent":2},
{"id":1,"parent":3},
{"id":2,"parent":5},
{"id":2,"parent":6},
{"id":2,"parent":7}
]

I have also tried to use .toString() in the values, but it didn't make any difference.

How could I solve it?

1
  • 1
    You should do your while loop until 0, since you are not checking if length equals 0. You are not reading the last one. Commented Aug 16, 2016 at 11:06

5 Answers 5

1

You could do this with reduce() and forEach() loop

var data = [{
  id: 1,
  parent: [1, 2, 3, 4]
}, {
  id: 2,
  parent: [5, 6, 7, 8]
}]

var result = data.reduce(function(r, ar) {
  ar.parent.forEach(function(e) {
    r.push({id: ar.id, parent: e});
  });
  return r;
}, []);

console.log(result)

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

1 Comment

Thanks. It works well. I decided to accept this answer, as the method you use is interesting and I didn't know it, so I will keep reading about that.
1

Is it what you needed?

var data = [
{
id: 1,
parent: [1,2,3,4]
}, 
{
id: 2,
parent: [5,6,7,8]
}
]

var updatedData = [];

data.forEach((obj) => {
  if (obj.parent.length > 1) {
    obj.parent.forEach((value) => {
      updatedData.push({
        id: obj.id,
        parent: [value]
      });
    })
  }
});

1 Comment

Thanks. It should be parent: value instead, as I wanted the value outside the array, but this is pretty much it.
1

Here we can use for loop to traverse the array:

var data = [
{
id: 1,
parent: [1,2,3,4]
}, 
{
id: 2,
parent: [5,6,7,8]
}
];
var result = [];
for(var i=0; i<data.length; i++) {
    var obj = data[i];
    for(var j=0;j<obj.parent.length; j++) {
        result.push({id: obj["id"], parent: obj.parent[j]});
    }
}
console.log(result);

THe result will print the expected result.

Comments

1

I will still write the answer to use you code correctly since you had something working :

for (var i = 0; i < updateddata[i].parent.length; i++) {
    while (updateddata[i].parent.length > 0) { // Here you should read the last one
        updateddata.push({
        id: updateddata[i].id,
        parent: updateddata[i].parent[0]
        })
        updateddata[i].parent.shift()
    }
}

Of course this will keep the empty array at the beginning. Two solutions, remove after treatment or when length = 1 change parent array into the value

Comments

1

I think reduce, concat, and map yield a more declarative solution.

var data = [
  { id: 1, parent: [1,2,3,4] }, 
  { id: 2, parent: [5,6,7,8] }
]

let result = data.reduce((acc, {id, parent}) =>
  [...acc, ...parent.map(x => ({id, parent:x}))], [])
   
console.log(result)

If you define the shape of the output data ahead of time, it makes things a bit better yet

var data = [
  { id: 1, parent: [1,2,3,4] }, 
  { id: 2, parent: [5,6,7,8] }
]

let shape = id => parent => ({id, parent})

let result = data.reduce((acc, {id, parent}) =>
  [...acc, ...parent.map(shape(id))], [])
   
console.log(result)

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.