Mandalina
Mandalina

Reputation: 446

Filtering array of objects and nested objects

I have an array of objects that looks like this:

  var data = [
  {
    type: "parent",
    children: [
      {
        type: "parent",
        children: [
            {
              type: "parent"
            },
            {
              type: "parent",
              children: [
                {
                 type: "notParent"
                },
                {
                 type: "parent"
                }
              ]
            }
        ]
      }
    ]
  },
  {
    type: "parent",
    children: [
      {
        type: "parent"
      }
    ]
  },
  {
    type: "parent",
    children: [
      {
        type: "parent",
        children: [
          {
            type: "parent"
          },
          {
            type: "parent"
          }
        ]
      },
      {
        type: "notParent"
      }
    ]
  },
  {
    type: "notParent"
  }
]

This data is an array of objects, and can have objects deeply nested. What I want to do is to create a new array that only contains the objects with the type: "parent" and remove all others. I am finding it hard to make this work for deeply nested objects. I have tried many variations of the following:

        var findAllParents = function(obj, type) {
            if(obj.type === type) { return obj; }
            for(var i in obj) {
                if(obj.hasOwnProperty(i)){
                    var foundParents = findAllParents(obj[i], type);
                    if(foundParents) { return foundParents; }
                }
            }
            return null;
        };

I would like for this to return data like this:

  var data = [
  {
    type: "parent",
    children: [
      {
        type: "parent",
        children: [
            {
              type: "parent"
            },
            {
              type: "parent",
              children: [
                {
                 type: "parent"
                }
              ]
            }
        ]
      }
    ]
  },
  {
    type: "parent",
    children: [
      {
        type: "parent"
      }
    ]
  },
  {
    type: "parent",
    children: [
      {
        type: "parent",
        children: [
          {
            type: "parent"
          },
          {
            type: "parent"
          }
        ]
      }
    ]
  }
]

Only to return all objects with type: "parent"

Upvotes: 1

Views: 124

Answers (2)

idmitrov
idmitrov

Reputation: 509

const data = [
    {
        type: "parent",
        children: [
            {
                type: "parent",
                children: [
                    {
                        type: "parent"
                    },
                    {
                        type: "parent",
                        children: [
                            {
                                type: "notParent",
                                children: [
                                    {
                                        type: "parent"
                                    }
                                ]
                            },
                            {
                                type: "parent"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        type: "parent",
        children: [
            {
                type: "parent"
            }
        ]
    },
    {
        type: "parent",
        children: [
            {
                type: "parent",
                children: [
                    {
                        type: "parent",
                        children: [
                            {
                                type: "parent",
                                children: [
                                    {
                                        type: "notParent"
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        type: "parent"
                    }
                ]
            },
            {
                type: "notParent"
            }
        ]
    },
    {
        type: "notParent"
    }
];

const filterCollectionItemsOfType = (collection, expectedType = 'parent') => {
    const filteredCollection = collection.filter((item) => item.type === expectedType);

    filteredCollection.forEach((item) => {
        if (item.children && item.children.length) {
            item.children = filterCollectionItemsOfType(item.children, expectedType);
        }
    });

    return filteredCollection;
}

const parentsCollection = filterCollectionItemsOfType(data);

console.log(parentsCollection);

Upvotes: 1

Maheer Ali
Maheer Ali

Reputation: 36564

You can make a copy of the data and then apply the recursive function which will remove the desired elements from the children array of each object using filter()

var data = [ { type: "parent", children: [ { type: "parent", children: [ { type: "parent" }, { type: "parent" } ] } ] }, { type: "parent", children: [ { type: "parent" } ] }, { type: "parent", children: [ { type: "parent", children: [ { type: "parent" }, { type: "parent" } ] }, { type: "notParent" } ] } ]

function remove(obj){
  if(obj.children){
    obj.children = obj.children.filter(x => x.type === "parent");
    obj.children.forEach(x => remove(x))
  }
}

let copy = JSON.parse(JSON.stringify(data));

copy.forEach(x => remove(x));

console.log(copy)

Upvotes: 0

Related Questions