【问题标题】:multiselect filter array with nested object具有嵌套对象的多选过滤器数组
【发布时间】:2018-11-16 17:23:17
【问题描述】:

我使用 vue-multiselect 让用户选择带有过滤选项的项目:

query = "what user type in input field"
allLinks.filter(l=>l.labelName.includes(query))

它可以工作,但现在我想用这种结构将过滤扩展到我的对象的所有属性:

{
    "labelName":"LK000056",
    "extPort":{
        "aPort":"EXTA-EQ001/board10port02",
        "zPort":"EXTZ-EQ012/board09port02"
    }
}

如果 labelName、aPort 或 zPort 上的查询匹配,我希望使用一个查询来获取父对象。

有可能吗?或者可能使用有条件的方式,例如:

allLinks.filter(l=>if(!l.labelName.includes(query)){l.extport.aPort.includes(query)}else{l.extport.zPort.includes(query)})

谢谢你帮助我

请原谅我的近似英语我是法国人

【问题讨论】:

    标签: javascript arrays filter nested multi-select


    【解决方案1】:

    您可以递归地将对象展平为字符串数组,然后通过Array.filterArray.someArray.includes 在其中搜索:

    const data = [{ "labelName":"LK000056", "extPort":{ "aPort":"EXTA-EQ001/board10port02", "zPort":"EXTZ-EQ012/board09port02" } }, { "labelName":"LK000057", "extPort":{ "aPort":"EXTA-EQ001/board123", "zPort":"EXTZ-EQ012/board333" } }]
    
    const flatten = (obj, a=[]) => Object.values(obj)
      .reduce((r,c) => (typeof c == 'object' ? flatten(c,a) : r.push(c), r), a)
    
    const search = (d, t) => 
      d.filter(x => flatten(x).some(x => x.toLowerCase().includes(t.toLowerCase())))
    
    console.log(search(data, 'board123'))
    console.log(search(data, 'LK000056'))
    console.log(search(data, 'EXTZ-EQ012'))

    请注意,这是一种通用方法,无论data 的嵌套级别如何,都可以使用,例如:

    const data = [{
      "A": {
        "B": {
          "C": {
            "data": '11'
          },
        }
      }
    }, {
      "D": {
        "E": {
          "data": '22'
        }
      }
    }, {
      "F": "33"
    }]
    
    const flatten = (obj, a = []) => Object.values(obj)
      .reduce((r, c) => (typeof c == 'object' ? flatten(c, a) : r.push(c), r), a)
    
    const search = (d, t) => d.filter(x => 
      flatten(x).some(x => x.toLowerCase().includes(t.toLowerCase())))
    
    console.log(search(data, '22'))
    console.log(search(data, '11'))
    console.log(search(data, '33'))

    【讨论】:

      【解决方案2】:

      您可以使用Object.values 以数组的形式获取对象的值,然后使用some 测试一个或多个项目是否匹配。

      const items = [{
        "labelName": "LK000056",
        "extPort": {
          "aPort": "EXTA-EQ001/board10port02",
          "zPort": "EXTZ-EQ012/board09port02"
        }
      }, {
        "labelName": "234234",
        "extPort": {
          "aPort": "abc123",
          "zPort": "1234567890"
        }
      }]
      
      function search(query, data) {
        return data.filter(i => {
          if (i.labelName.includes(query)) return true
          if (Object.values(i.extPort).some(v => v.includes(query))) return true
          return false
        })
      }
      
      console.log(search("EQ001", items))
      console.log(search("1234567890", items))
      console.log(search("lalalala", items))

      【讨论】:

        【解决方案3】:

        如果它可以帮助我认为找到了一个实用的解决方案,请告诉我是否可以做更好的事情......

        allLinks.filter(l=>{
            if (l.sdhPort.zSDHPort!=undefined && l.extPort.aPort.toUpperCase().includes(query.toUpperCase())){return true}
            if (l.extport.zPort!=undefined && l.extPort.zPort.toUpperCase().includes(query.toUpperCase())){return true}
            if (l.labelName!=undefined && l.labelName.toUpperCase().includes(query.toUpperCase())){return true}
        })
        

        【讨论】:

          【解决方案4】:

          哇,谢谢你们!

          这个技术看起来真的很有趣......但是让我有时间去理解它

          对我的发现有什么看法?

          最好的问候

          【讨论】:

          • 您应该删除此答案,因为答案仅用于回答问题。您应该对答案发表评论。
          • 好的,我会删除它并为每个回复做出回答。感谢您的提示
          猜你喜欢
          • 2019-05-22
          • 1970-01-01
          • 2022-01-06
          • 1970-01-01
          • 1970-01-01
          • 2021-11-21
          • 2021-05-16
          • 2020-03-11
          • 2020-03-08
          相关资源
          最近更新 更多