0

I currently have a collection of data called venues that contain the following fields:

const venues = [ { name: 'test1', categories: ['1a', '1b'], currencies: ['2a', '2b'] }, { name: 'test2', categories: ['1b'], currencies: ['2a'] } ] 

The categories/currencies fields within each venue object contain the ids of the category they belong to and the currencies they accept.

I then have an array of filters that looks like the following:

const filters = [ { name: 'art', id: '1a', type: 'categories' }, { name: 'testCurrency', id: '2b', type: 'currencies' }, ] 

In order to chain the filters for currencies and categories I am doing the following:

 const filterVenueData = (venues, filterByType, key) => { const filteredVenues = venues.filter((venue) => { if (!filterByType[key]?.length) return true return filterByType[key].some((filters) => { return venue[key].includes(filters.id) }) }) return filteredVenues } const filtersByType = filters.reduce( (hash, obj) => ({ ...hash, [obj['type']]: (hash[obj['type']] || []).concat(obj) }), {} ) const filterByCategory = filterVenueData( venues, filtersByType, 'categories' ) const filterByCurrency = filterVenueData( filterByCategory, filtersByType, 'currencies' ) console.log(filterByCurrency) 

while this works... I can't help but feel like having to call the function twice (and pass in the key to filter by) in order to chain the filters for both currency and categories seems very inefficient. Is there a way to chain the filters using a loop as opposed to having to call the function twice/pass in what key to filter by? I would like the filters to be strict, meaning in this current example, only venues who belong to the art category and accept testCurrency should appear (test1 venue).

I have attached a code sandbox for debugging: https://codesandbox.io/s/serverless-rain-dmluz?file=/src/index.js

1 Answer 1

1

Instead of using filterVenueData for each type of filter, use the filtersByType object and iterate over its entries - check that .every one of its entries passes the test (that is, that the venue contains one of the IDs).

const venues=[{name:"test1",categories:["1a","1b"],currencies:["2a","2b"]},{name:"test2",categories:["1b"],currencies:["2a"]}],filters=[{name:"art",id:"1a",type:"categories"},{name:"testCurrency",id:"2b",type:"currencies"}]; const filtersByType = {}; for (const { id, type } of filters) { filtersByType[type] ??= []; filtersByType[type].push(id); } const output = venues.filter(obj => Object.entries(filtersByType).every(([key, arr]) => arr.some(id => obj[key].includes(id)) ) ); console.log(output);

Sign up to request clarification or add additional context in comments.

3 Comments

this is exactly what I was looking for. Question, can you explain the filtersByType[type] ??= []
Equivalent to if (filtersByType[type] === undefined || filtersByType[type] === null) filtersByType[type] = [];
really appreciate it!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.