简体   繁体   English

具有嵌套对象的多选过滤器数组

[英]multiselect filter array with nested object

I use vue-multiselect to let user select items with filtering options: 我使用vue-multiselect来让用户选择带有过滤选项的项目:

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

and it works, but now I would like to extend the filtering to all properties of my object with this structure : 并且它可以工作,但是现在我想使用这种结构将过滤扩展到对象的所有属性:

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

I would like with one query to get parent object if query match on labelName, aPort or zPort. 我想用一个查询来获取父对象,如果在labelName,aPort或zPort上查询匹配。

it is possible ? 有可能的 ? or maybe with a conditional way like : 或可能采用类似的条件方式:

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

thank for helping me 谢谢你帮我

forgive my approximate English I am French 原谅我大约英语我是法国人

You could recursively flatten the objects to array of strings, then search in them via Array.filter , Array.some & Array.includes : 您可以将对象递归展平为字符串数组,然后通过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')) 

Note that this is a generic approach and will work regardless of the nested levels of data , for example: 请注意,这是一种通用方法 ,无论嵌套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')) 

You can use Object.values to get the values of the object as an array, then use some to test if one or more items match. 您可以使用Object.values来获取对象的值作为一个数组,然后用一些测试,如果一个或多个项目相匹配。

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

if it can help I think found a functional solution let me know if something better can be done ... 如果它可以帮助我认为找到了功能解决方案,请告诉我是否可以做得更好...

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

wow thanks both of you ! 哇,谢谢你们!

it seems really interesting this technic ... but let me some time to understand it 这个技术看起来真的很有趣...但是让我花一些时间来了解它

what do think about what I found ? 我如何看待发现?

best regards 最好的祝福

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

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