简体   繁体   English

在循环中链接过滤器

[英]Chaining Filters within a Loop

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.每个场地对象中的类别/货币字段包含它们所属类别的 ID 以及它们接受的货币。

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).我希望过滤器是严格的,这意味着在当前示例中,只有属于艺术类别并接受 testCurrency 的场地才会出现(test1 场地)。

I have attached a code sandbox for debugging: https://codesandbox.io/s/serverless-rain-dmluz?file=/src/index.js我附上了一个用于调试的代码沙箱: https : //codesandbox.io/s/serverless-rain-dmluz?file=/ src/ index.js

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).代替使用filterVenueData对于每种类型的过滤器的,使用filtersByType在其条目对象和迭代-检查.every其条目中的一个通过了测试(即,场内包含ID中的一个)。

 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM