Home > Enterprise >  How to filter an array inside an array by an array field?
How to filter an array inside an array by an array field?

Time:11-20

I am facing one problem when I want to filter an array inside an array by an array. Please see the example-

const array1 = [
    {
        name: "this is name1",
        products: [
            { id: "4" },
            { id: "2" },
        ]
    },
    {
        name: "this is name2",
        products: [
            { id: "2" },
            { id: "1" }
        ]
    }
]

const array2 = [
    { id: "1", refund: true },
    { id: "2", refund: false },
    { id: "3", refund: true },
    { id: "4", refund: false}
]

Here I have to filter array1 products field. Here in array1 products filed an array with of id. I have to filter this products field by searching same object from array2 by id and then filter when refund is true.

From the example I need result by this-

const array1 = [
    {
        name: "this is name2",
        products: [
            { id: "1" }
        ]
    }
]

Here in result we can see only one object in this array. Because from array1, in the object's product filed have two id 4 and 2. From array2 we can see refund false for both id 4 and 2. That's why array1 remove first object.

In the second object we can see products field contain two id 2 and 1. From array2 we can see refund is false for id 2 but refund is true for id 1. Hence for id 1 refund is true that's why it stay in products array.

Please help me. I hope I can clear my questions.

CodePudding user response:

You can use a combination of array methods like filter, map & reduce to get the result.

const array1 = [
  {
    name: 'this is name1',
    products: [{ id: '4' }, { id: '2' }],
  },
  {
    name: 'this is name2',
    products: [{ id: '2' }, { id: '1' }],
  },
];

const array2 = [
  { id: '1', refund: true },
  { id: '2', refund: false },
  { id: '3', refund: true },
  { id: '4', refund: false },
];

// Transforms array2 to { 1: { id: 1, refund: true }, 2: ...}  
const array2ToMap = array2.reduce((map, item) => {
    map[item.id] = item
    return map
}, new Map());

const result = array1
  .map(item => {
    // Filters only the products that have refund as `true`
    const filteredProducts = item.products.filter(
      product => array2ToMap[product.id]?.refund
    );
    return { ...item, products: filteredProducts };
  })
  // Only select items which have at least 1 filtered products
  .filter(item => item.products.length > 0);

console.log(result);

CodePudding user response:

const array1 = [{"name":"this is name1","products":[{"id":"4"},{"id":"2"}]},{"name":"this is name2","products":[{"id":"2"},{"id":"1"}]}];
const array2 = [{"id":"1","refund":true},{"id":"2","refund":false},{"id":"3","refund":true},{"id":"4","refund":false}];

const refundIds = array2.filter(i=>i.refund).map(i=>i.id);
const intersect = (a,b) => a.some(i=>b.includes(i));

console.log(array1.filter(e=>
  intersect(refundIds, e.products.map(i=>i.id)))
  .map(({products, ...a})=>({...a,
    products: products.filter(i=>refundIds.includes(i.id))
  }))
);

  • Related