Filter a list of objects based on a list property compared against a list

Viewed 35

I have a list of objects in following format.

let information = [
    {
        data: {
            list: [ 'item1', 'item4', 'item5'],
        }
    },
    {
        data: {
            list: [ 'item100', 'item200', 'item300'],
        }
    },
    {
        data: {
            list: [ 'item1', 'item2', 'item3'],
        }
    },
    {
        data: {
            list: [ 'item70', 'item71', 'item300'],
        }
    }
]

I have a dynamic list coming from another selection which could look like this.

const dynamicList = ['item1', 'item71'];

I wish to filter out objects from information where there is at least 1 match when compared to dynamicList.

So in above example, after filtering, I should be left with only 3 items.
Only 2nd item has neither item1 nor item71 in it, so remaining 3 is a match.

Attempted the following to filter.

But the result is 4 so nothing got filtered. Second data has no item1 it in its list.
Why has it not been filtered? Please advice. Thanks.

console.log(information.length); // 4

information = information
.filter(info => info.data.list !== null)
.filter(info => info.data.list
    .filter(item => dynamicList.includes(item)));

console.log(information.length); // still 4, should be 3

P.S: Above code can be pasted as it on a browser console to try it out.

2 Answers

You could filter the elements whose list contains at least one element of dynamicList using .some() :

let information = [
    {
        data: {
            list: [ 'item1', 'item4', 'item5'],
        }
    },
    {
        data: {
            list: [ 'item100', 'item200', 'item300'],
        }
    },
    {
        data: {
            list: [ 'item1', 'item2', 'item3'],
        }
    },
    {
        data: {
            list: [ 'item70', 'item71', 'item300'],
        }
    }
];

const dynamicList = ['item1', 'item71'];

let filteredList = information.filter(info => info.data.list.some(el => dynamicList.includes(el)));

console.log(filteredList);

This may be one possible solution to achieve the desired objective:

Code Snippet

const filterUsing = (dlist, iarr) => (
  iarr.filter(
    ({data : { list }}) => list && list.some(x => dlist.some(y => x === y))
  )
);
// instead of dlist.some(y => x === y), may also use dlist.includes(x)
const information = [{
    data: {
      list: ['item1', 'item4', 'item5'],
    }
  },
  {
    data: {
      list: ['item100', 'item200', 'item300'],
    }
  },
  {
    data: {
      list: ['item1', 'item2', 'item3'],
    }
  },
  {
    data: {
      list: ['item70', 'item71', 'item300'],
    }
  }
];

const dynamicList = ['item1', 'item71'];

console.log('filtered-array:', filterUsing(dynamicList, information));
console.log('length: ', filterUsing(dynamicList, information).length);

Explanation

  • A method filterUsing takes two params - dlist (dynamicList) and iarr (information array)
  • Apply .filter() on iarr
  • Destructure iarr element to access data.list
  • Check if there is some element in list such that the same is present in dlist.
Related