3

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"}]}]}]
5
  • um, if you want the players with active status, why do you want the country and the games array? Commented Jan 9, 2021 at 13:25
  • @TheBombSquad Because I need to display their values as well! Commented Jan 9, 2021 at 13:28
  • @Sam this question might help stackoverflow.com/questions/38375646/… Commented Jan 9, 2021 at 13:29
  • I've seen it before, but the filter applied there for the first level only, and I couldn't do it inside the players list. @OzgurSar Commented Jan 9, 2021 at 13:38
  • just solved.. nested filter logic i used Commented Jan 9, 2021 at 14:19

4 Answers 4

3

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)
Sign up to request clarification or add additional context in comments.

Comments

2

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)

Comments

1

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)

Comments

1

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"
          }
        ]
      }
    ]
  }
]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.