0

I want to filter out data from a multilayered JSON object:

    var players = [
    0:{
        id: "1"
        stats: 
        { 
          yellow_cards: "0" 
          saves: "0" 
        }
        explain: 
        [
        0:{
            fixture: "251"   
            stats: [
            0:{
                identifier: "minutes"
                points: "2" 
                value: "75"
              }  
            ] 
          }
        1:{ 
            fixture: "191" 
            stats: 
            [
            0:{
                identifier: "minutes"
                points: "2" 
                value: "83"
              }  
            1:{
                identifier: "assists"
                points: "3"
                value: "1"
              }
            ]
          }
        ]
      }
    ]    

I want to sort out the players who have at least one object where identifier = "minutes" and the value is between 50 and 60. If I loop through everything it works fine:

var selected = [];
  for(i=0; i<players.length; i++){
    for(j=0; j<players[i].explain.length; j++){
      for(k=0; k<players[i].explain[j].stats.length;k++){
        if(players[i].explain[j].stats[k].identifier == "minutes"){
          if(players[i].explain[j].stats[k].value >50 && players[i].explain[j].stats[k].value < 60) { 
            selected.push(players[i]);
          }
        }
      }
    }
  }

This takes too much time, and I'm sure there is a more elegant way to do this with array filter and find function. Any help with this is highly appreciated.

Edit: In order to keep it short the array above shows only one object which doesn't fulfill the criteria.

2
  • 1
    Please try: selected = players.filter(({ explain }) => explain.some(({ stats }) => stats.some(({ identifier, value }) => ( identifier === 'minutes' && value > 50 && value < 60 )))); and share your feedback. It's pretty self-explanatory code - but if required, we can have an answer posted with explanations. Commented Jun 9, 2022 at 11:42
  • 1
    Ran some scenarios and it worked great, will have to run a couple of more, but this seems to be exactly what I was looking for. Thanks! Commented Jun 9, 2022 at 11:53

1 Answer 1

1

Instead of using this tradition for loop for nested filtering, you can achieve the same requirement via Array.filter() along with Array.some()

Here is the performance check with both the approaches : jsbench

enter image description here

Demo :

var players = [{
  id: "1",
  stats: { 
    yellow_cards: "0", 
    saves: "0" 
  },
  explain: [{
    fixture: "251", 
    stats: [{
      identifier: "minutes",
      points: "2",
      value: "75"
    }] 
  }, { 
    fixture: "191", 
    stats: [{
      identifier: "minutes",
      points: "2",
      value: "83"
    }, {
      identifier: "assists",
      points: "3",
      value: "1"
    }]
  }]
}];

const selected = players.filter(({ explain }) => {
  return explain.some(({ stats }) => {
    return stats.some(({ identifier, value }) => {
      return identifier === "minutes" && (value > 50 && value < 60)
    })
  })
})

console.log(selected);

Sign up to request clarification or add additional context in comments.

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.