简体   繁体   中英

Javascript filter an array of objects by a property of object

I have an array of userList which include user basic information.

this.state = {
    userList: [
        { name:"Ann", number:123456789 },
        { name:"Cathy", number:123456789 },
        { name:"Peter", number:123456789 },
        { name:"Ben", number:123456789 },
    ],
    vips: [ 
        { username:"Ann", years:2018 },
        { username:"Peter", years:2019 },
};

How I can return of the vips from userList ? vips.username equals to userList.name

vips_return: [
        { name:"Ann", number:123456789 },
        { name:"Peter", number:123456789 },
]

I tried using .filter and .includes but I am not sure how to deal with objects.

const vips_return = userList.filter((user)=>
    vips.includes(user.name)
)

You can use find or findIndex :

userList.filter(user => vips.find(vip => vip.username === user.name));

find returns undefined if the value cannot be found in the array, so those are filtered out.

If you do this a lot and/or have a large data set, you should build a set of names first:

const vipNames = new Set(vips.map(vip => vip.username));

userList.filter(user => vipNames.has(user.name));

You can use a reduce and get the users in userList which are also in vips

 const input = { userList: [ { name:"Ann", number:123456789 }, { name:"Cathy", number:123456789 }, { name:"Peter", number:123456789 }, { name:"Ben", number:123456789 }, ], vips: [ { username:"Ann", years:2018 }, { username:"Peter", years:2019 }, ] }; console.log(input.userList.reduce((acc, val) => { if(!!input.vips.find(vip => vip.username === val.name)) { acc.push(val); } return acc; }, [])); 

Considering that the length of vips should be lower than the one of userList , or at max the same ( vips should be a subset of userList ), maybe a better approach is to map over the vips and get back the corresponding user, like below:

 const input = { userList: [ { name:"Ann", number:123456789 }, { name:"Cathy", number:123456789 }, { name:"Peter", number:123456789 }, { name:"Ben", number:123456789 }, ], vips: [ { username:"Ann", years:2018 }, { username:"Peter", years:2019 }, ] }; console.log(input.vips.map(vip => input.userList.find(user => user.name === vip.username))); 

You could take a Map and get the wanted objects.

 var state = { userList: [{ name: "Ann", number: 123456789 }, { name: "Cathy", number: 123456789 }, { name: "Peter", number: 123456789 }, { name: "Ben", number: 123456789 }], vips: [{ username: "Ann", years: 2018 }, { username: "Peter", years: 2019 }] }, user = new Map(state.userList.map(o => [o.name, o])), vips = state.vips.map(({ username }) => user.get(username)); console.log(vips); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Or take a shorter approach with a double mapping

 var state = { userList: [{ name: "Ann", number: 123456789 }, { name: "Cathy", number: 123456789 }, { name: "Peter", number: 123456789 }, { name: "Ben", number: 123456789 }], vips: [{ username: "Ann", years: 2018 }, { username: "Peter", years: 2019 }] }, vips = state.vips .map(({ username }) => username) .map(Map.prototype.get, new Map(state.userList.map(o => [o.name, o]))); console.log(vips); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

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