user2849732
user2849732

Reputation: 49

How to filter array of objects with nested arrays of objects based on other arrays

Sample code.

const cards = [
    {
        id: "1",
        name: "J",
        tag: [
          {
            "colour": "red"
          },
          {
            "colour": "yello"
          },
          {
            "colour": "blue"
          },
          {
            "colour": "white"
          },
        ],
        size: [
          {
            "name": "small"
          },
          {
            "name": "medium"
          },
        ],
    },
    {
        id: "2",
        name: "S",
        tag: [
          {
            "colour": "red"
          },
          {
            "colour": "green"
          },
          {
            "colour": "black"
          },
        ],
        size: [
          {
            "name": "small"
          },
          {
            "name": "medium"
          },
        ],
    },
    {
        id: "3",
        name: "K",
        tag: [
          {
            "colour": "green"
          },
          {
            "colour": "purple"
          },
          {
            "colour": "brown"
          },
          {
            "colour": "white"
          },
        ],
        size: [
          {
            "name": "large"
          },
        ],
    }
];

Test arrays

const sizeArray = ["medium", "small"];
const tagArray = ["red", "black"];

I want the filtered array of objects to only include the second object in this example. Filtering only those who match all criteria leaving me with a new array of objects.

I've tried with .filter, .some, .includes and no luck looking over many other answers to similar questions.

Thanks a lot.

Upvotes: 0

Views: 63

Answers (2)

DecPK
DecPK

Reputation: 25408

You can use the filter with every and some.

Since you need to filter the result which contains all sizeArray and tagArray in size and tag array respectively.

const cards = [
  {
    id: "1",
    name: "J",
    tag: [
      {
        colour: "red",
      },
      {
        colour: "yello",
      },
      {
        colour: "blue",
      },
      {
        colour: "white",
      },
    ],
    size: [
      {
        name: "small",
      },
      {
        name: "medium",
      },
    ],
  },
  {
    id: "2",
    name: "S",
    tag: [
      {
        colour: "red",
      },
      {
        colour: "green",
      },
      {
        colour: "black",
      },
    ],
    size: [
      {
        name: "small",
      },
      {
        name: "medium",
      },
    ],
  },
  {
    id: "3",
    name: "K",
    tag: [
      {
        colour: "green",
      },
      {
        colour: "purple",
      },
      {
        colour: "brown",
      },
      {
        colour: "white",
      },
    ],
    size: [
      {
        name: "large",
      },
    ],
  },
];

const sizeArray = ["medium", "small"];
const tagArray = ["red", "black"];

const result = cards.filter(({ tag, size }) =>
    sizeArray.every((s) => size.some((si) => si.name === s)) &&
    tagArray.every((t) => tag.some((ta) => ta.colour === t))
);

console.log(result);

Upvotes: 3

Nick
Nick

Reputation: 16576

As you filter the main array, you want to make sure at least one of the tag values is in the tagArray and at least one of the size values is in the sizeArray. This can be achieved using includes.

const cards=[{id:"1",name:"J",tag:[{colour:"red"},{colour:"yello"},{colour:"blue"},{colour:"white"}],size:[{name:"small"},{name:"medium"}]},{id:"2",name:"S",tag:[{colour:"red"},{colour:"green"},{colour:"black"}],size:[{name:"small"},{name:"medium"}]},{id:"3",name:"K",tag:[{colour:"green"},{colour:"purple"},{colour:"brown"},{colour:"white"}],size:[{name:"large"}]}];

const sizeArray = ["medium", "small"];
const tagArray = ["red", "black"];

const filtered = cards.filter((card) => {
  return (
    card.tag.some((tag) => tagArray.includes(tag.colour)) &&
    card.size.some((size) => sizeArray.includes(size.name))
  );
});

console.log(filtered);

Note that includes isn't super efficient, but I'm assuming you're not working with tons of data here. If your sizeArray or tagArray are especially large, you could look into something like the Set object for hash table efficiency.

Upvotes: 2

Related Questions