Reputation: 45
I have an array which I'm trying to filter based on a certain nested value, without getting any other elements.
const arrayData = [
{
country: "Country X",
games: [
{
gameTitle: 'Game1',
players: [{ name: 'John', status:'Active' },{ name: 'Rob', status:'Suspended' }]
},
{
gameTitle: 'Game2',
players: [{ name: 'Saly', status:'Blocked' }]
},
]
},
{
country: "Country Y",
games: [
{
gameTitle: 'Game1',
players: [{ name: 'Sindy', status:'Pending' },{ name: 'someone', status:'Rejected' }]
},
{
gameTitle: 'Game2',
players: [{ name: 'Alex', status:'New' },{ name: 'Nic', status:'Old' }]
},
]
},
];
What I have tried:
let output = arrayData.filter(eachVal => {
let opt = eachVal.games.some((
{ players }) => players
.some(({ status}) => status === 'Active'));
return opt;
})
Expected result for finding all players with value status : 'Active':
{
country: "Country X",
games: [
{
gameTitle: 'Game1',
players: [{ name: 'John', status:'Active' }]
}
]
}
But the result:
[{"country":"Country X","games":[{"gameTitle":"Game1","players":[{"name":"John","status":"Active"},{"name":"Rob","status":"Suspended"}]},{"gameTitle":"Game2","players":[{"name":"Saly","status":"Blocked"}]}]}]
Upvotes: 3
Views: 212
Reputation: 4327
The logic is nested filter through each level and assigning the finds back to their respective places and using forEach
logic to see if an object has an "Active" value
const arrayData = [
{
country: "Country X",
games: [
{
gameTitle: 'Game1',
players: [{ name: 'John', status:'Active' },{ name: 'Rob', status:'Suspended' }]
},
{
gameTitle: 'Game2',
players: [{ name: 'Saly', status:'Blocked' }]
},
]
},
{
country: "Country Y",
games: [
{
gameTitle: 'Game1',
players: [{ name: 'Sindy', status:'Pending' },{ name: 'someone', status:'Rejected' }]
},
{
gameTitle: 'Game2',
players: [{ name: 'Alex', status:'New' },{ name: 'Nic', status:'Old' }]
},
]
},
];
//answer
let arr=JSON.parse(JSON.stringify(arrayData))
arr=arr.filter(a=>{
let f=a.games; let i=false
f=f.filter(b=>{
let x=b.players; let j=false
x=x.filter(c=>c.status=="Active")
x.forEach(c=>{if(c.status=="Active"){j=true}})
b.players=x; return j
})
f.forEach(b=>{
b.players.forEach(c=>{if(c.status=="Active"){i=true}})
})
a.games=f; return i
})
console.log(arr)
Upvotes: 2
Reputation: 525
Try this:
arrayData.map(({country, games: g}) => {
const games = g.map((g) => {
const players = g.players.filter((p) => p.status === 'Active')
return {...g, players}
})
.filter(({players}) => players.length > 0)
return {country, games}
}).filter(({games}) => games.length>0)
Upvotes: 3
Reputation: 1905
It's quite easy. You just need some map
and filter
:
const arrayData = [
{
country: "Country X",
games: [
{
gameTitle: 'Game1',
players: [{ name: 'John', status:'Active' },{ name: 'Rob', status:'Suspended' }]
},
{
gameTitle: 'Game2',
players: [{ name: 'Saly', status:'Blocked' }]
},
]
},
{
country: "Country Y",
games: [
{
gameTitle: 'Game1',
players: [{ name: 'Sindy', status:'Pending' },{ name: 'someone', status:'Rejected' }]
},
{
gameTitle: 'Game2',
players: [{ name: 'Alex', status:'New' },{ name: 'Nic', status:'Old' }]
},
]
},
];
/*------------------------------- This is the answer -------------------------------*/
let result = arrayData.map(a => ({...a, games: a.games.map(g => ({...g, players: g.players.filter(p => p.status === 'Active')})).filter(g => g.players.length)})).filter(a => a.games.length)
/*----------------------------------------------------------------------------------*/
console.log(result)
Upvotes: 1
Reputation: 809
I'd "recursively" select the valid elements at each level and map on each filtered array to build the correct output:
const selectActivePlayers = (players) => players.filter(player => player.status === "Active");
const selectValidGames = (games) => games.filter(game => selectActivePlayers(game.players).length > 0)
const selectValidCountries = (countries) => countries.filter(country => selectValidGames(country.games).length > 0);
const cleanCountries = selectValidCountries(arrayData).map(country => ({
...country,
games: selectValidGames(country.games).map(game => ({
...game,
players: selectActivePlayers(game.players)
}))
}))
Output:
[
{
"country": "Country X",
"games": [
{
"gameTitle": "Game1",
"players": [
{
"name": "John",
"status": "Active"
}
]
}
]
}
]
Upvotes: 1