【问题标题】:Multiple Data Filtering多重数据过滤
【发布时间】:2019-11-22 20:03:41
【问题描述】:

请帮我做正确的多重过滤,按城市、标签、距离过滤应该是可以的,而且每个分类有很多项,例如:

城市:莫斯科、圣彼得堡、基辅、华沙、伦敦

标签:马拉松、半程马拉松、接力

距离:7公里、22公里、100公里、42公里

您可以标记任意数量的项目以进行过滤

var events = [
{id: 0, date:"22.12.2019", name:"event1", city:"Moscow", distances:"100km", tags:[{id: 0, name: Marathon},{id: 1, name: Half Marathon}]},
{id: 1, date:"22.12.2019", name:"event2", city:"London", distances:"22km", tags:[{id: 0, name: Relay}]},
{id: 2, date:"22.12.2019", name:"event3", city:"Moscow", distances:"42km", tags:[{id: 0, name: Marathon},{id: 1, name: Relay}]},
{id: 3, date:"22.12.2019", name:"event4", city:"Kiev", distances:"100km", tags:[{id: 0, name: Marathon},{id: 1, name: Half Marathon},{id: 2, name: Эстафета}]},
{id: 4, date:"22.12.2019", name:"event5", city:"Warsaw", distances:"42km", tags:[{id: 0, name: Marathon}]},
{id: 5, date:"22.12.2019", name:"event6", city:"St. Petersburg", distances:"22km", tags:[{id: 0, name: Relay},{id: 1, name: Half Marathon}]},
{id: 6, date:"22.12.2019", name:"event7", city:"St. Petersburg", distances:"7km", tags:[{id: 0, name: Half Marathon}]},
]

如果我选择马拉松、接力、42km、100km 进行过滤,那么最好的过滤方式是什么,你可以选择不同的选项 我尝试了什么:我在过滤器的类别下创建了 3 个数组,当我点击这些项目时,我将它写到所需的数组中,然后我像这样运行它:

const { filterCity } = this.state; // array of selected filters by city
    const { eventById } = this.props.Events.eventsList.events; // all events
    const allEvents = (eventById === null ? [] : eventById); //data check 
    const filtered = allEvents.filter((events) => {
      // eslint-disable-next-line no-plusplus
      for (let i = 0; i < filterCity.length; i++) {
        // eslint-disable-next-line no-plusplus
        for (let j = 0; j < events.tags.length; j++) {
          if (filterCity.indexOf(events.tags[j].name) !== -1) {
            return false;
          }
        }
      }
      return true;
    });

到目前为止,只是为了过滤城市,但是在这里你可以选择你想要的城市,以不同的顺序,会有规范,但我做对了吗,因为我想马上把这个功能添加到其他类别中,这样它会检查所有内容,结果是更多的内部循环,也许可以做得更好,或者请告诉我规范

附:我纯粹在 js 上使用 react 任务

【问题讨论】:

    标签: javascript reactjs filter


    【解决方案1】:

    也许您可以这样做,将过滤器作为具有单个键/值对的对象数组传递。然后,您可以单独过滤它们,如果至少有一个过滤器匹配,则返回事件。

    这应该允许您过滤多个过滤器类别,以及这些类别中的多个值。

    const filters = [{ city: 'Moscow' }, { city: 'Kiev' }, { distances: '42km'} ];
    
    events.filter(event => {
    
        // will return true if one of the filtered values is present in the event object
        return filters.some(filter => {
            return hasFilteredProperty(event, filter);
        });
    
    });
    
    // Pass filter as { key: value }
    const hasFilteredProperty = (event, filterObj) => {
    
        const filterKey = Object.keys(filterObj)[0];
    
        if (filterKey === 'tags') {
            return hasFilteredTags(event, filterObj[filterKey]);
        } else {
            return event[filterKey] === filterObj[filterKey];
        }
    
    }
    
    // Pass filtered tags as an array of names: [ 'Half Marathon', 'Marathon', '100km' ]
    const hasFilteredTags = (event, filteredTags) => {
    
        const eventTagNames = event.tags.map(tag => tag.name);
        return eventTagNames.some(tagName => filteredTags.includes(tagName));
    
    }
    

    【讨论】:

    • 用一个简单的对象就可以了,但是“标签”字段呢,那里有一个对象数组?他们也必须通过过滤器,但此选项不会过滤它们
    • 我已经更新了我的答案以包含一个示例,但这实际上取决于您的过滤器的数据结构,我目前并不确切知道。显然,这个示例没有考虑不区分大小写之类的问题,但它应该让您了解如何进行操作。
    • 现在它可以与标签一起使用,但是有什么问题,例如,如果我们选择城市“莫斯科”作为过滤器,过滤器选择“半程马拉松”,它将显示在至少遇到一件事,但是过滤器的想法是选择城市“莫斯科”,过滤器“半程马拉松”应该只输出事件中所有过滤器匹配的地方
    • Hm .. 从您最初的问题中并不清楚,但在这种情况下,您需要修改匹配函数以执行不同的操作。现在,这些功能确实以至少匹配一个的方式工作。如果你想匹配所有你应该能够使用every 而不是some
    • 我用 evry 替换了所有的 soms,它不起作用,它甚至坏了,它只检查一个键,例如“城市”,如果还有“标签”我不'这个键都不看,我在控制台里查过
    【解决方案2】:

    您可以使用数组includes 函数来检查filterCity 中是否存在事件城市。对于其他类似的属性,您可以执行相同的操作。对于标签,因为事件属性本身是一个对象数组,您可以首先使用map 创建标签名称数组,然后检查filterTag 中的至少一个元素是否存在。演示代码如下。

    let filterCity = ['Moscow', 'Russia']
    let filterTag = ['Relay','Marathon']
    let filteredEvent = events.filter(event => {
      if(filterCity.length && !filterCity.includes(event.city)) return false
       if(filterTag.length && event.tags.map(tag => tag.name).find(tag => filterTag.indexOf(tag)>-1)==undefined) return false
     return true
    })
    
    console.log(filteredEvent)
    

    【讨论】:

    • 如果 filterCity 为空并且 filterTag = ['Half Marathon','Marathon'] 那么它将找到所有有 Half Marathon 或 Marathon 标签的事件,只有那些有标签的事件应该找到半程马拉松和马拉松
    • 否则一切正常,但使用标签就不太对了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 2021-05-02
    • 2021-02-05
    • 2020-05-04
    • 2016-11-06
    • 2019-02-06
    • 1970-01-01
    相关资源
    最近更新 更多