Michał B
Michał B

Reputation: 473

Filtering through json subarrays

I have a problem with filtering array in my JSON file.

When I'm using a filter in the main array it works but I cannot do this in subarrays.

This is JSON file:

[
    {
        "id": 1354,
        "name": "name",
        "type": "simple",
        "status": "ok",
        "categories": [
            {
                "id": 79,
                "name": "A",
            },
            {
                "id": 68,
                "name": "B",
            }
        ]
    },
    {
        "id": 1368,
        "name": "name",
        "type": "simple",
        "status": "ok",
        "categories": [
            {
                "id": 79,
                "name": "A",
            },
            {
                "id": 72,
                "name": "C",
            }
        ]
    },
    {...}
]

I'm using this code to filter and it works as expected and returns items with status: 'ok':

return items.filter( item => {
    return item.status == 'ok';
});

What I want to archive is to return items which have category.name: 'B'.

This code seems to work only with the first category and if the item's first category is not 'B' then this item is not showing:

return items.filter( item => {
    for (let category of item.categories) {
        return category.name == 'B';
    }
});

Thanks for any ideas

Upvotes: 2

Views: 269

Answers (4)

Vova Rozhkov
Vova Rozhkov

Reputation: 1732

You've returned right after the first category check. You should continue iteration if category name is not matching required pattern and return false only after all iterations.

return items.filter(item => {
    for (let category of item.categories) {
      if (category.name === 'B') {
        return true;
      }
    }
    return false;
});

Upvotes: 1

wscourge
wscourge

Reputation: 11291

Try using Array.prototype.some() instead - it returns true only if some of the array elements fulfills passed condition.

const whole = [
    {
        "id": 1354,
        "name": "name",
        "type": "simple",
        "status": "ok",
        "categories": [
            {
                "id": 79,
                "name": "A",
            },
            {
                "id": 68,
                "name": "B",
            }
        ]
    },
    {
        "id": 1368,
        "name": "name",
        "type": "simple",
        "status": "ok",
        "categories": [
            {
                "id": 79,
                "name": "A",
            },
            {
                "id": 72,
                "name": "C",
            }
        ]
    },
    {
        "id": 1364,
        "name": "name",
        "type": "simple",
        "status": "ok",
        "categories": [
            {
                "id": 71,
                "name": "B",
            },
            {
                "id": 70,
                "name": "C",
            }
        ]
    },
]

const filtered = whole.filter(level_1 => {
  return level_1.categories.some(level_2 => level_2['name'] === 'B')
})

console.log(filtered);

Upvotes: 1

Aaditya Thakkar
Aaditya Thakkar

Reputation: 1820

You can do something like this:

  return items.filter( item => {
        return item.categories.findIndex(category => category.name === 'B') > -1
    });

Upvotes: 0

baao
baao

Reputation: 73251

You're returning too early in your for loop. What you are looking for is some:

const res = arr.filter(e => e.categories.some(({name}) => name === 'B'));
console.log(res);
<script>
const arr = [
    {
        "id": 1354,
        "name": "name",
        "type": "simple",
        "status": "ok",
        "categories": [
            {
                "id": 79,
                "name": "A",
            },
            {
                "id": 68,
                "name": "B",
            }
        ]
    },
    {
        "id": 1368,
        "name": "name",
        "type": "simple",
        "status": "ok",
        "categories": [
            {
                "id": 79,
                "name": "A",
            },
            {
                "id": 72,
                "name": "C",
            }
        ]
    },

]
</script>

Upvotes: 1

Related Questions