简体   繁体   中英

How to filter an array based on a nested array 4 level deep?

I have an object like this:

let accessArray = [{
      id: 1,
      restrictions: [{
         canAccess: true,
         users: [{
            name: 'user',
            accessLevel: [10, 20, 30]
         }]
      }]
   },
   {
      id: 2,
      restrictions: [{
         canAccess: true,
         users: [{
            name: 'user2',
            accessLevel: [10, 20]
         }]
      }]
   }
]

I would like to know how I filter to get only the accessArray items that contains the accessLevel 30 which in the example is the item with id = 1 .Thanks.

You could write a nested some :

 const accessArray = [{id:1,restrictions:[{canAccess:true,users:[{name:'user',accessLevel:[10,20,30]}]}]},{id:2,restrictions:[{canAccess:true,users:[{name:'user2',accessLevel:[10,20]}]}]}] const level = 30; function getAccess(level) { return accessArray.filter(a => a.restrictions.some(b => b.users.some(c => c.accessLevel.includes(level)))) } console.log(getAccess(30))

(This assumes that the nested arrays at least empty [] and none of them are null or undefined )

I suspect the restrictions and users arrays can have multiple elements, not always just one, so you can do this :

 let accessArray = [{ id: 1, restrictions: [{ canAccess: true, users: [{ name: 'user', accessLevel: [10, 20, 30] }] }] }, { id: 2, restrictions: [{ canAccess: true, users: [{ name: 'user2', accessLevel: [10, 20] }] }] } ] let output = accessArray.filter( obj => obj.restrictions.some( restriction => restriction.users.some( user => user.accessLevel.includes(30) ) ) ) console.log(output)

In this example, it returns true if any of the users has accessLevel 30. If you need all users to have accessLevel 30, then replace .some with .every .

You could iterate all objects and look for the wanted key and of this value is an array, then check for the value, otherwise call the function again for all other found objects.

This works without knowing the path to the wanted nested property. It works for any depth.

 const has = (key, value) => function iter(o) { return Object.entries(o).some(([k, v]) => k === key && Array.isArray(v) && v.includes(value) || v && typeof v === 'object' && iter(v) ); }; var array = [{ id: 1, restrictions: [{ canAccess: true, users: [{ name: 'user', accessLevel: [10, 20, 30] }] }] }, { id: 2, restrictions: [{ canAccess: true, users: [{ name: 'user2', accessLevel: [10, 20] }] }] }], result = array.filter(has('accessLevel', 30)); console.log(result);
 .as-console-wrapper { max-height: 100% !important; top: 0; }

You can use the filter function to only return what you want:

 let accessArray = [{ id: 1, restrictions: [{ canAccess: true, users: [{ name: 'user', accessLevel: [10, 20, 30] }] }] }, { id: 2, restrictions: [{ canAccess: true, users: [{ name: 'user2', accessLevel: [10, 20] }] }] } ] console.log(accessArray.filter(a => a.restrictions.some(b => b.users.some( c => c.accessLevel.includes(30)))))

This will check multiple users in multiple restriction objects

accessArray.filter(arr => {
    return arr.restrictions.filter(re => {
        return re.users.filter(user => user.accessLevel.includes(30)).length>0;
    }).length>0;
})

Or in a single line

accessArray.filter(arr => arr.restrictions.filter(re => re.users.filter(user => user.accessLevel.includes(30)).length>0).length>0)
accessArray.filter(arr => arr.restrictions.filter(re => re.users.filter(user => user.accessLevel.includes(30))))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM