rebilliony
rebilliony

Reputation: 187

Recursive looping over array of objects using reduce

I have an array of objects with children. The goal is to remove every item from items arrays.

Is it possible to do without using forEach and map loops? How to use reduce in this case?

The problem is some arrays have items on one level and others have children array with items inside. Sample here:

{
  "label": "child1",
  "children": [
    {
      "label": "child2",
      "items": [
        "item1",
        "item2"
      ]
    },
    {
      "label": "child3",
      "items": [
        "item1",
        "item2",
        "item3"
      ]
    }
  ]
}

As a result, I want to see a mutated array of objects with empty items arrays. Here`s an object to be mutated:

[
  {
    "label": "parent",
    "children": [
      {
        "label": "child1",
        "children": [
          {
            "label": "child2",
            "items": [
              "item1",
              "item2"
            ]
          },
          {
            "label": "child3",
            "items": [
              "item1",
              "item2",
              "item3"
            ]
          }
        ]
      },
      {
        "label": "child4",
        "items": []
      },
      {
        "label": "child5",
        "items": ["item1","item2"]
      }
    ]
  }
]

And here is my incomplete solution:

function flattenDeep(arr) {
  return arr.reduce(
    (acc, val) =>
      Array.isArray(val)
        ? acc.concat(flattenDeep(val.children))
        : acc.concat(val.children),
    []
  );
}

Upvotes: 0

Views: 123

Answers (1)

KooiInc
KooiInc

Reputation: 122936

Here's a way to empty all items arrays.

The idea is to use a predefined reducer method that can you can use recursively.

const reducer = (reduced, element) => {
  // empty items array
  if (element.items) {
    element.items.length = 0;
  }
  // if element has children, recursively empty items array from it
  if (element.children) {
   element.children = element.children.reduce(reducer, []);
  }
  return reduced.concat(element); // or: [...reduced, element]
};

document.querySelector("pre").textContent = 
   JSON.stringify(getObj().reduce(reducer, []), null, " ");

// to keep relevant code on top of the snippet
function getObj() {
  return [
    {
      "label": "parent",
      "children": [
        {
          "label": "child1",
          "children": [
            {
              "label": "child2",
              "items": [
                "item1",
                "item2"
              ]
            },
            {
              "label": "child3",
              "items": [
                "item1",
                "item2",
                "item3"
              ]
            }
          ]
        },
        {
          "label": "child4",
          "items": []
        },
        {
          "label": "child5",
          "items": ["item1","item2"]
        }
      ]
    }
  ];
}
<pre></pre>

Upvotes: 1

Related Questions