Home > Software engineering >  How can I filter/find in (casecading) array of arrays json
How can I filter/find in (casecading) array of arrays json

Time:01-24

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.

CodePudding user response:

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)

CodePudding user response:

You can use some(), which is a bit more declarative and stops searching on hit:

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.some((size) => {
        size.id === sizeid && 
        size.colors.some((color) => {
            color.id === colorid
        })
    })
})

CodePudding user response:

You can make a nested for loop, skipping ids that do not match at each level, and set an exists flag if there is an exact match at the innermost loop.

const items = [
  {
    "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",
          }

        }]
    }
  }
]


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

let exists = false;
for (let item of items) {
    if (item.id != itemid) continue;
    if (item.zone.id != zoneid) continue;
    for (let size of item.zone.sizes) {
        if (size.id != sizeid) continue;
        for (let color of size.colors) {
            if (color.id != colorid) continue;
            exists = true;
        }
    }
}

console.log(exists)

  • Related