【发布时间】:2022-01-03 04:18:36
【问题描述】:
我有一个对象数组options,类似于:
const options = [
{
"apiName": "tomato",
"category": "veggie",
"color": "red",
"price": "90"
},
{
"apiName": "banana",
"category": "fruit",
"color": "yellow",
"price": "45"
},
{
"apiName": "brinjal",
"category": "veggie",
"color": "violet",
"price": "35"
},
]
我想使用类似于
的过滤条件对象(动态生成)过滤这个数组Example filterGroup 1
let filterGroup = {
type: 'and',
filters: [
{
key: 'category',
condition: 'is',
value: 'veggie'
type: 'filter'
},
{
key: 'price',
condition: 'is less than',
value: '45',
type: 'filter'
}
]
}
Example filterGroup 2
let filterGroup = {
key: 'category',
condition: 'is',
value: 'veggie'
type: 'filter'
}
在上面的filterGroup 对象中,filters 数组中的每个元素都充当单独的过滤器,options 中的每个option 都应该满足这些过滤器。
condition 的可能值为is、is not、is less than 和is greater than。
如何使用 JavaScript 以最有效的方式使用 conditions 对象过滤 options 数组?
我尝试过的(REPL 链接 - https://replit.com/@pcajanand/DarkseagreenEnlightenedTests#index.js),
制作了一些过滤器函数创建者
const eq = (propertyAccessKey, compareValue) => (item) => (item[propertyAccessKey] === compareValue)
const ne = (propertyAccessKey, compareValue) => (item) => (item[propertyAccessKey] === compareValue)
const lt = (propertyAccessKey, compareValue) => (item) => (item[propertyAccessKey] < compareValue)
const gt = (propertyAccessKey, compareValue) => (item) => (item[propertyAccessKey] > compareValue)
制作了一个函数来创建带有单个过滤器的过滤器函数(类型=过滤器)
const makeFilterFunction = ({condition, value, key}) => {
if (condition === 'is') {
return (eq(key, value))
} else if (condition === 'is greater than') {
return (gt(key, value))
} else if (condition === 'is less than') {
return (lt(key, value))
} else if (condition === 'is not') {
return (ne(key, value))
}
}
创建过滤器函数并将它们推送到数组中,
let fnArray = []
if (filters.type === 'and') {
filters.filters.forEach((filter) => {
fnArray.push(makeFilterFunction(filter))
})
} else if (filters.type === 'filter') {
fnArray.push(makeFilterFunction(filters))
}
遍历每个选项,检查每个过滤条件,然后将传递所有条件的项目作为过滤结果推送到数组。
const res = opts.reduce((acc, next) => {
let fnIndex = 0
let fnArrayLength = fnArray.length
let itemPassed = true
while(fnIndex < fnArrayLength) {
const fnPassed = fnArray[fnIndex](next)
if (!fnPassed) {
itemPassed = false
break
}
fnIndex += 1
}
if (itemPassed) {
return acc.concat(next)
} else {
return acc
}
}, [])
虽然这可行(我认为?),但我想知道是否有其他更有效的方法可以做到这一点。或者,如果我完全遗漏了某些东西并且使事情变得过于复杂。
TLDR - 想要过滤具有多个链接条件的对象数组。
此处为非英语母语者,如果问题含糊不清,请见谅。 感谢阅读!
【问题讨论】:
-
filterGroup的例子不一样,第一个有顶级的type属性。那是什么? -
您只有一个嵌套过滤器,还是可以无限?
-
@Titus 基本上 filterGroup 可以以任何一种形式出现。如果它只有一个过滤器,它将具有 type = 'filter'。否则它将有 type = 'and' (意味着所有过滤器都使用 and 组合)。
-
@NinaScholz 不,对于我们的用例,只有一层嵌套。所以不会有类似 (Filter1 & Filter 2) ||过滤器 3。但如果我能覆盖类似的东西,那将是一个奖励。
标签: javascript arrays reactjs json filtering