wasddd_
wasddd_

Reputation: 1018

Filter nested array for specific value

I have a simple array like this:

const test = [{
  test: 1,
  key: [{
    yes: true,
    no: null
  },{
    yes: true,
    no: null
  },{
    yes: false,
    no: null
  }]
},
{
  test: true,
  key: [{
    yes: true,
    no: null
  }]
},
{
  test: null,
  key: [{
    yes: null,
    no: null
  }]
}
];

And I want to return an array which will only include items where test is truthy (e.g. 1). And the key array inside of test will only include objects with a truthy value for key.yes.

So the expected output is:

[
   {
     test: 1,
     key: [{yes: true, no: null},{yes: true, no: null}]
   },
   {
     test: true,
     key: [{yes: true, no: null}]
   }
];

I tried to achieve this by using a simple filter like this:

const filtered = test.filter(obj => obj.test && obj.key.filter(item => item.yes).length > 0)

but this returns also the values of the key array which are false.

Any ideas why?

Upvotes: 1

Views: 305

Answers (3)

Grzesiek Danowski
Grzesiek Danowski

Reputation: 467

You should first filter main array and then remap to new filtering subbarray, for example:

const filtered = test
   .filter(obj => obj.test && obj.key.some(item => item.yes))
   .map(d => {d.test, key: d.key.filter(item => item.yes));

Or probably filter array by key.yes a moment later:

const filtered = test
   .filter(obj => obj.test)
   .map(d => {d.test, key = d.key.filter(item => item.yes))
   .filter(s => s.key);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386519

You need to get a new outer array and new inner arrays, because the outer filtering does not change the inner arrays. If you mutate the inner array and filter the outer array, you mutate the given data.

For getting an independent result, you could check test and if truthy filter key and get a new object for the result set.

var test = [{ test: 1, key: [{ yes: true, no: null }, { yes: true, no: null }, { yes: false, no: null }] }, { test: true, key: [{ yes: true, no: null }] }, { test: null, key: [{ yes: null, no: null }] }],
    result = test.reduce((r, { test, key }) => {
        if (test) {
            r.push({ test, key: key.filter(({ yes }) => yes) });
        }
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 2

Explosion Pills
Explosion Pills

Reputation: 191729

You will have to filter each individual key array as well.

// array where `test` is truthy
const filtered = test.filter(({ test }) => !!test);

// array where sub-arrays are filterd
const final = filtered.map(({ key }) => key.filter(({ yes }) => !!yes));

Upvotes: 0

Related Questions