tom harrison
tom harrison

Reputation: 3423

Filtering an array in react with multiple values

I'm trying to filter one array so that the objects will display if they match one of the options at the filterOptions (another array).

Example: If filterOptions contains the string big it should show the objects with sizes containing the string big

However, I'm not sure how to split data.sizes correctly so it can use this data to filter with, how can I do this?

https://codesandbox.io/s/thirsty-ellis-dplhg

export const App = () => {
  const data = [
    {sizes: 'big,small',},
    {sizes: 'medium,small'},
    {sizes: 'small,big',},
    {sizes: 'big',},
    {sizes: 'medium',}
  ];

  const filterOptions = ['big', 'small'];
  const splitData = data.map(items => items.sizes.split(','));

  return(
    <div>
      {console.log(splitData)}
      {data.filter(items => items.sizes.includes(filterOptions))
           .map(item => <div>{item.sizes}<br /></div>)}
    </div>
  )
}

Upvotes: 1

Views: 2916

Answers (4)

Shidersz
Shidersz

Reputation: 17190

I believe you are looking for:

{data.filter(i => i.sizes.split(",").some(size => filterOptions.includes(size)))
     .map(item => <div>{item.sizes}<br/></div>)}

Example of the filter result:

const data = [
  {sizes: 'big,small'},
  {sizes: 'medium,small'},
  {sizes: 'small,big'},
  {sizes: 'big'},
  {sizes: 'medium'}
];

const filterOptions = ['big','small'];

let res = data.filter(
    i => i.sizes.split(",").some(
        size => filterOptions.includes(size)
    )
);

console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

However, for your particular set of sizes ("small", "big" and "medium"), where there are no string that is also substring of another string, you can go with the next filter using a regular expression constructed from the filterOptions array:

const data = [
  {sizes: 'big,small'},
  {sizes: 'medium,small'},
  {sizes: 'small,big'},
  {sizes: 'big'},
  {sizes: 'medium'}
];

const filterOptions = ['big','small'];

let res = data.filter(
    ({sizes}) => new RegExp(filterOptions.join("|")).test(sizes)
);

console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Or, in your context of code:

{data.filter(({sizes}) => new RegExp(filterOptions.join("|")).test(sizes))
     .map(item => <div>{item.sizes}<br/></div>)}

Upvotes: 1

Vishnu
Vishnu

Reputation: 897

Are you looking for

const data = [
    {
      sizes: 'big,small',
    },
    {
      sizes: 'medium,small'
    },
    {
      sizes: 'small,big',
    },
    {
      sizes: 'big',
    },
    {
      sizes: 'medium',
    }
  ];

const filterOptions = ['big','small'];

const filterData = data.filter( d => filterOptions.every(f => d.sizes.split(',').includes(f)));

console.log(filterData);

Upvotes: 0

Yannick K
Yannick K

Reputation: 5412

Here's how you might go about it (there are a lot of different ways to achieve your result though):

const data = [
  { sizes: 'big,small', },
  { sizes: 'medium,small' },
  { sizes: 'small,big', },
  { sizes: 'big', },
  { sizes: 'medium', }
];

const filterOptions = [ "big", "small" ];
const filterData = data.filter( ( { sizes } ) => {
  for ( const filter of filterOptions ) {
    if ( sizes.includes( filter ) ) {
      return true;
    }
  }
} );

console.log( filterData );

This is assuming of course you don't want the data sizes to contain both filterOptions.

Upvotes: 0

fangzhzh
fangzhzh

Reputation: 2252

this answer can fit as many filter options as possible

data.filter(items => items.sizes.split(',').find(size => filterOptions.includes(size)))

Upvotes: 2

Related Questions