Troy Henne
Troy Henne

Reputation: 11

Deep Filtering Array of Objects Javascript

We're trying to wrap our heads around this for awhile and can't seem to get what we're looking for. We've attempted many loops and using lodash library to make this possible but no success. We want to loop through the arrays and return any objects and children that have the property checked:true or remove the objects that have checked: false. There are multiple levels deep and we're not able to return what we're looking for

types: [
  {
    name: 'Dresses',
    checked: true,
    collections: [
      {
        name: 'My Collection',
        checked: true,
        variations: [
          { 
            size: 'XXS',
            checked: true

          },
          { 
            size: 'XS',
            checked: false

          }
        ]
      },
      {
        name: 'False Collection',
        checked: false,
        variations: [
          { 
            size: 'XXS',
            checked: false

          },
          { 
            size: 'XS',
            checked: false

          }
        ]
      }
    ]
  },
  {
    name: 'Tops',
    checked: true,
    collections: [
      {
        name: 'Another Collection',
        checked: true,
        variations: [
          { 
            size: 'XXS',
            checked: false

          },
          { 
            size: 'XS',
            checked: true

          }
        ]
      }
    ]
  }
]

Our Expected output that we are trying to generate would be:

types: [
      {
        name: 'Dresses',
        checked: true,
        collections: [
          {
            name: 'My Collection',
            checked: true,
            variations: [
              { 
                size: 'XXS',
                checked: true

              }
            ]
          }
        ]
      },
      {
        name: 'Tops',
        checked: true,
        collections: [
          {
            name: 'Another Collection',
            checked: true,
            variations: [
              { 
                size: 'XS',
                checked: true

              }
            ]
          }
        ]
      }
    ]

Which removes any object with the property checked: false

Upvotes: 1

Views: 1002

Answers (2)

Yuri Gor
Yuri Gor

Reputation: 1463

If you are using lodash, I suggest to use filterDeep method from deepdash:

var filtrate = _.filterDeep(types, function(value, key, parent) {
  if (parent.checked) return true;
});

Here is a test for your case

Upvotes: 1

Scott Sauyet
Scott Sauyet

Reputation: 50807

I usually choose to use Ramda for such problems. (Disclaimer: I'm one of its authors.) With Ramda, you could do it like this:

const types = [{"checked": true, "collections": [{"checked": true, "name": "My Collection", "variations": [{"checked": true, "size": "XXS"}]}], "name": "Dresses"}, {"checked": true, "collections": [{"checked": true, "name": "Another Collection", "variations": [{"checked": true, "size": "XS"}]}], "name": "Tops"}]

const {is, filter, pipe, toPairs, map, fromPairs} = R;
 
const onlyChecked = (obj) => 
  is(Array, obj) 
  ? filter(onlyChecked, obj)
  : is(Object, obj)
    ? pipe(
        toPairs,
        filter(([key, val]) => val.checked !== false),
        map(([key, val]) => [key, onlyChecked(val)]),
        fromPairs
      )(obj)
    : obj;

console.log(onlyChecked(types))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

This should be easy to port to lodash, as the key functions such as fromPairs and toPairs are included in both, and Ramda's is(Array)/is(Object) are very similar to lodash's isArray/isObject.

Upvotes: 0

Related Questions