【问题标题】:Dynamic array filtering by object property按对象属性过滤动态数组
【发布时间】:2018-11-14 17:36:53
【问题描述】:

我有一个实时搜索下拉组件,它通过搜索词过滤一组对象。它按标题过滤我的对象,然后返回所有相关对象的列表。这工作正常。

当前:

数据结构

data: [
    { id: 1, title: 'Some title here' },
    { id: 2, title: 'Another title' },
    { id: 3, title: 'last title' },
]

组件

   <LiveSearch
        term={term}
        data={data} />

实时搜索组件内部

按术语过滤数据并呈现列表

return data
        .filter(item => item.title.toLowerCase().includes(term.toLowerCase())
        .map((item, idx) => <li key={idx}>{item.title}</li>

我的搜索对象变得越来越高级,我希望能够将一组属性名称传递给我的组件,我想将其与搜索词进行比较。

我的思考过程是循环遍历对象属性,如果其中一个属性与术语匹配,则循环中断并返回 true,将该对象添加到要显示的项目列表中。

目标

数据结构

data: [
    { id: 1, country: 'Canada', title: 'Some title here' },
    { id: 2, country: 'Australia', title: 'Another title' },
    { id: 3, country: 'Netherlands', title: 'last title' },
]

组件

<LiveSearch
   searchFields={['country', 'title']}
   term={term}
   data={data} />

内部组件过滤

return data
         .filter(item => {
            // Dynamic filtering of terms here
         })
         .map((item, idx) => <li key={idx}>{item.title}</li>

在过滤器内部,我试图通过数组循环并动态生成与此类似的逻辑

item.searchFields[0].toLowerCase().includes(term.toLowerCase()) ||
item.searchFields[1].toLowerCase().includes(term.toLowerCase())

但显然可以循环无限数量的搜索字段/属性

【问题讨论】:

    标签: javascript arrays filter


    【解决方案1】:

    使用Array#some()

    类似

    term = term.toLowerCase()
    return data
      .filter(item => {
        return searchFields.some(field => item[field].toLowerCase().includes(term))
      }).map(...
    

    【讨论】:

      【解决方案2】:

      检查some 是否与searchFields 匹配:

      // Checks wether a value matches a term
      const matches = (value, term) => value.toLowerCase().includes(term.toLowerCase());
      
       // Checks wether one of the fields in the item matcues the term
       const itemMatches = (fields, term) => item => fields.some(field => matches(item[field], term);
      
       // Filter the data to only contain items where on of the searchFields matches the term
       const result = props.data.filter( itemMatches(props.searchFields, props.term) );
      
       return result.map(item => <li key={idx}>{item.title}</li>);
      

      【讨论】:

        【解决方案3】:

        您可以将数组.some.filter结合使用

        let result = data.filter(obj => 
          searchFields.some(s => 
          obj[s] != undefined && obj[s].toLowerCase() === term
        ));
        

        let data = [
            { id: 1, country: 'Canada', title: 'Some title here' },
            { id: 2, country: 'Australia', title: 'Another title' },
            { id: 3, country: 'Netherlands', title: 'last title' },
        ], searchFields = ["country", "title"], term = "canada";
        
        let result = data.filter(obj => 
          searchFields.some(s => 
          obj[s] != undefined && obj[s].toLowerCase() === term
        ));
        
        console.log(result);

        【讨论】:

        • 这真是太复杂了。
        • @JonasWilms 可能吗?这不是真正的建设性评论。需要详细说明吗?
        • 那个flag ?我的意思是你总是检查所有的属性,你实际上可以在第一次找到后退出。
        猜你喜欢
        • 1970-01-01
        • 2019-05-04
        • 2020-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-18
        • 1970-01-01
        • 2015-06-21
        相关资源
        最近更新 更多