Map and reduce array of objects with a children array down to array of children with parent's id

11,109

Solution 1

This should do it:

var values = [{
    "id": "uniqueParentId1",
    "children": [{
      "childProp1": "test1",
      "childProp2": "test3"
    }]
  },
  {
    "id": "uniqueParentId2",
    "children": [{
        "childProp1": "somevals",
        "childProp2": "other vals"
      },
      {
        "childProp1": "somevals 1",
        "childProp2": "other vals 1"
      }
    ]
  }
];

var result = values.map(value =>
  value.children.map(child => ({ parentId: value.id, ...child }))
).flat();

console.log(result);

A breakdown of the code:

child => ({ parentId: value.id , ...child })

Takes an object and returns a new object with the parentId property and all of the properties in child.

Input:

{
    "childProp1": "somevals",
    "childProp2": "other vals"
}

Output:

{
    "parentId": "uniqueParentId2"
    "childProp1": "somevals",
    "childProp2": "other vals"
}

Next function:

value =>
    value.children.map(child => ({ parentId: value.id, ...child }))

Takes an object named value, applies the function above to each of the array elements in value.children, and returns an array of the results.

Next:

values.map(.....)

Applies the function above to each of the elements in values and returns an array of the results.

At this point, the result of this .map() call is an array like the following, with one element for each element of the original array:

[
  [
    {
      "parentId": "uniqueParentId1",
      "childProp1": "test1",
      "childProp2": "test3"
    }
  ],
  [
    {
      "parentId": "uniqueParentId2",
      "childProp1": "somevals",
      "childProp2": "other vals"
    },
    {
      "parentId": "uniqueParentId2",
      "childProp1": "somevals 1",
      "childProp2": "other vals 1"
    }
  ]
]

So the last thing we do is flatten flatten this array with .flat().

Solution 2

const arr = [
  {
    "id": "uniqueParentId1",
    "children": [
      {
        "childProp1": "test1",
        "childProp2": "test3"
      }
    ]
  },
  {
    "id": "uniqueParentId2",
    "children": [
      {
        "childProp1": "somevals",
        "childProp2": "other vals"
      },
      {
        "childProp1": "somevals 1",
        "childProp2": "other vals 1"
      }
    ]
  }
];
let combined = [];
arr.forEach((parent) => {
  const {id, children} = parent;
  children.forEach((child) => {
    Object.assign(child, {
      parentId: id
    });
    combined.push(child);
  });
});

console.log(combined);
/*
[
  {
    "parentId": "uniqueParentId1",
    "childProp1": "test1",
    "childProp2": "test3"
  },
  {
    "parentId": "uniqueParentId2",
    "childProp1": "somevals",
    "childProp2": "other vals"
  }
  {
    "parentId": "uniqueParentId2",
    "childProp1": "somevals 1",
    "childProp2": "other vals 1"
  }
]
*/
Share:
11,109

Related videos on Youtube

user1738539
Author by

user1738539

Updated on September 15, 2022

Comments

  • user1738539
    user1738539 over 1 year

    I'm trying to take an array of objects like this

    [
      {
        "id": "uniqueParentId1",
        "children": [
          {
            "childProp1": "test1",
            "childProp2": "test3"
          }
        ]
      },
      {
        "id": "uniqueParentId2",
        "children": [
          {
            "childProp1": "somevals",
            "childProp2": "other vals"
          },
          {
            "childProp1": "somevals 1",
            "childProp2": "other vals 1"
          }
        ]
      }
    ]
    

    And return an array of all the children combined, with each child object having an additional value, the "id" of the parent.

    Above examples, result.

    [
      {
        "parentId": "uniqueParentId1",
        "childProp1": "test1",
        "childProp2": "test3"
      },
      {
        "parentId": "uniqueParentId2",
        "childProp1": "somevals",
        "childProp2": "other vals"
      }
      {
        "parentId": "uniqueParentId2",
        "childProp1": "somevals 1",
        "childProp2": "other vals 1"
      }
    ]
    

    I'm just not sure how to approach this. I'm familiar with flattening and array of arrays. But I'm only able to get the output as an array of the original children without adding the parentId

  • AP.
    AP. over 6 years
    Like your solution! Maybe add a few lines explaining your code, so other people not as familiar with functional js can understand your solution?
  • JLRishe
    JLRishe over 6 years
    @AP. Thanks for the suggestion. Added an explanation, but it turned out to be more than a few lines. :)
  • Daniel H.
    Daniel H. about 2 years
    Great solution, thanks! How would you do this if there are multiple nested arrays/objects?