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"}]}]}]
Sam
  • 45
  • 1
  • 7

4 Answers4

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)
Scott Gnile
  • 482
  • 4
  • 7
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)
The Bomb Squad
  • 4,192
  • 1
  • 9
  • 17
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"
          }
        ]
      }
    ]
  }
]
Nicoowr
  • 770
  • 1
  • 10
  • 29
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)
Amir
  • 1,885
  • 3
  • 19
  • 36