Search code examples
javascriptarraysjsonfilterfind

How can I filter/find in (casecading) array of arrays json


I'm trying to write js code to find if any item already exits in the array, it makes it a bit tricky. There are multiple items, every item has a zone, every zone has multiple sizes and every size has multiple colors. colors array sometime could be null.

I'm trying to find a way to filter/find item by itemid, zoneid, sizeid and colorid if these all four ids are found then it should be considered as item already exists in the array. But if same color id exist in different size or item then its not a match, here is simplified version of json

[
  {
    "id": 1,
    "title": "Item 1",
    "image": {
      "id": 5,
      "title": "Title image",
    },
    "zone": {
      "id": 3,
      "title": "example title",
      "zone": {
        "id": 1,
        "name": "zome name",
        "zoneCode": 1
      },
      "sizes": [
        {
          "id": 9,
          "SizeName": "Example name",
          "colors": [
            {
              "id": 1,
              "sizeId": 9,
              "itemColor": {
                "id": 1,
                "title": "Color1",
                "code": "#fff"
              }
            },
            {
              "id": 2,
              "sizeId": 9,
              "itemColor": {
                "id": 2,
                "title": "Color2",
                "code": "#f0f"
              }
            }           
          ],
          "itemSize": {
            "id": 1,
            "title": "title",
          },
          "style": {
            "id": 1,
            "name": "None",
          }

        }]
    }
  }
]

and here is how I'm trying to achieve it and looking for nicer and simpler approach.

let itemid = 1
let zoneid = 1        
let sizeid = 1
let colorid = 2

let items = items.filter((item) => {
    item.id == itemid && item.zone.id == zoneid && item.sizes.filter((size) => {
        size.id == sizeid && size.colors.filter((color) => {
            color.id == colorid
        })
    })
})

I'm looking for two different results from this. To verify the results I want to return array of items with more simpler approach and also I want to know how can I simply return the result in true/false form.


Solution

  • As long as the sizeid and colorid are expected to be found in the same size item, this could be the most straightforward approach.

    Anyway I'm quite sure you already have an answer like this:

    const filterBy = (data, {
        itemid,
        zoneid,
        sizeid,
        colorid
      }) =>
      data.filter(item =>
        item.id == itemid &&
        item.zone.id == zoneid &&
        item.zone.sizes.some(size =>
          size.id == sizeid &&
          size.colors.some(color =>
            color.id == colorid)
        )
      )
    

    The comparison is not by identity using === so there's tolerance that may result in some fake positives but in very shady circumstances.

    const data = [{
      "id": 1,
      "title": "Item 1",
      "image": {
        "id": 5,
        "title": "Title image",
      },
      "zone": {
        "id": 3,
        "title": "example title",
        "zone": {
          "id": 1,
          "name": "zome name",
          "zoneCode": 1
        },
        "sizes": [{
          "id": 9,
          "SizeName": "Example name",
          "colors": [{
              "id": 1,
              "sizeId": 9,
              "itemColor": {
                "id": 1,
                "title": "Color1",
                "code": "#fff"
              }
            },
            {
              "id": 2,
              "sizeId": 9,
              "itemColor": {
                "id": 2,
                "title": "Color2",
                "code": "#f0f"
              }
            }
          ],
          "itemSize": {
            "id": 1,
            "title": "title",
          },
          "style": {
            "id": 1,
            "name": "None",
          }
    
        }]
      }
    }];
    
    const filterBy = (data, {
        itemid,
        zoneid,
        sizeid,
        colorid
      }) =>
      data.filter(item =>
        item.id == itemid &&
        item.zone.id == zoneid &&
        item.zone.sizes.some(size =>
          size.id == sizeid &&
          size.colors.some(color => color.id == colorid)
        )
      )
    
    const filter = {
      itemid: 1,
      zoneid: 3,
      sizeid: 9,
      colorid: 1
    }
    const filtered = filterBy(data, filter)
    
    console.log(filtered)