[英]Javascript - Loop through an array of options and return an object when the object's property values match all values in the options array?
I am working on a filtering feature that filters through a rendered list of data.我正在研究过滤功能,该功能可以通过呈现的数据列表进行过滤。 My goal is to be able to filter data objects with user selected filters and return any data object that matches all of the selected filter options.
我的目标是能够使用用户选择的过滤器过滤数据对象并返回与所有选定过滤器选项匹配的任何数据对象。
So for example, here is a simulated array of selected options:例如,这是一个模拟的选定选项数组:
//This simulates a current filter options array
const filterOptions = ['Black', 'Green', '10.00', 'Wacky', 'false'];
Here is an example of the data array and object properties I would be comparing these values against:这是我将比较这些值的数据数组和对象属性的示例:
const data = {
games: [
{
name: 'Game1',
color: 'Black',
price: '1.00',
theme: 'Lucky',
licensed: true
},
{
name: 'Game2',
color: 'Pink',
price: '1.00',
theme: 'Multiple',
licensed: true
},
{
name: 'Game3',
color: 'Black',
price: '5.00',
theme: 'Crossword',
licensed: false
},
{
name: 'Game4',
color: 'Green',
price: '5.00',
theme: 'Lucky',
licensed: true
},
{
name: 'Game5',
color: 'Black',
price: '10.00',
theme: 'Wacky',
licensed: false
},
{
name: 'Game6',
color: 'Green',
price: '10.00',
theme: 'Wacky',
licensed: false
},
]
}
Considering the above mentioned simulated filter options, I would expect to see Game5 & Game6
.考虑到上面提到的模拟过滤器选项,我希望看到
Game5 & Game6
。 Both are 10.00
, are either Black or Green
, have the wacky
theme and have a false
value for license
.两者都是
10.00
,要么是Black or Green
,都有wacky
主题,并且有一个false
的license
值。
My thinking is that it would be easier to drop the use of the 'loose values' array, and possibly create an object with arrays of the selected filter options, with the property of those options arrays being the name of the property I intend to compare it against in the data object.我的想法是,放弃使用“松散值”数组会更容易,并且可能会创建一个包含所选过滤器选项数组的对象,这些选项数组的属性是我打算比较的属性的名称它反对在数据对象中。
For example:例如:
`const filterOptions =
{
color: ['Black', 'Green'],
price: ['10.00'],
theme: ['Wacky'],
licensed: [false]
}`
And then, I could use something like Object.keys(filterOptions)
to make it possible to loop the selected filter options object.然后,我可以使用
Object.keys(filterOptions)
类的东西来循环选定的过滤器选项对象。 My only thing here is that it seems for every game, I would need to loop the filterOptions
object like so:我唯一的事情是似乎对于每个游戏,我都需要像这样循环
filterOptions
对象:
const filterOptionsKeys = Object.keys(filterOptions);
const { games } = data;
games.forEach(game => {
//Game loop
console.log(game)
//Loop through filterOptions key array
filterOptionsKeys.forEach(key => {
console.log(key);
//Loop through each index of the filterOptions option arrays
filterOptions[key].forEach(option => {
console.log(option); //Assuming this is where I would make the comparisons
})
})
})
In total, it seems like I would need 2 internal forEach()
loops for every iteration of games.forEach()
.总的来说,对于
games.forEach()
每次迭代,我似乎需要 2 个内部forEach()
循环。 The data object I am working with returns just over 5000 game objects, and I feel like this approach would be extremely time consuming with a data array that large.我正在处理的数据对象只返回 5000 多个游戏对象,我觉得这种方法对于如此大的数据数组会非常耗时。
I am pretty stumped on my approach to this, and I am worried I will get to entrenched in doing this a certain way that in the end, will not be sufficient.我对我的处理方法感到非常困惑,我担心我会根深蒂固地以某种方式这样做,最终是不够的。 Is there maybe something I could make use of in
lodash
that would aid in doing something like this?也许我可以在
lodash
中使用一些东西来帮助做这样的事情? I have used the lodash
library on occasion, but I am not sure how I could apply it to something with this many matching conditions.我偶尔使用过
lodash
库,但我不确定如何将它应用于具有这么多匹配条件的东西。 So my question to sum this all up, would be: what is a smart way to approach this?所以我的问题是:什么是解决这个问题的聪明方法?
While iterating over the objects, check that .every
one of the object's values (except the name
) (cast to strings, if needed) are included in the filterOptions
array:在迭代对象时,检查
.every
对象的值(除了name
)(如果需要,转换为字符串)都包含在filterOptions
数组中:
const filterOptions = ['Black', 'Green', '10.00', 'Wacky', 'false']; const data = { games: [{ name: 'Game1', color: 'Black', price: '1.00', theme: 'Lucky', licensed: true }, { name: 'Game2', color: 'Pink', price: '1.00', theme: 'Multiple', licensed: true }, { name: 'Game3', color: 'Black', price: '5.00', theme: 'Crossword', licensed: false }, { name: 'Game4', color: 'Green', price: '5.00', theme: 'Lucky', licensed: true }, { name: 'Game5', color: 'Black', price: '10.00', theme: 'Wacky', licensed: false }, { name: 'Game6', color: 'Green', price: '10.00', theme: 'Wacky', licensed: false }, ] } const matchingObjects = data.games.filter( ({ name, ...game }) => Object.values(game).every( value => filterOptions.includes(String(value)) ) ); console.log(matchingObjects);
The "loose" values aren't a problem as long as you can come up with consistent rules for them, the code is still quite concise.只要你能为它们提出一致的规则,“松散”值就不是问题,代码仍然非常简洁。
If you're worried about performance (though it probably doesn't matter), if the filterOptions
can have a reasonable number of items, you can use a Set instead of an array.如果您担心性能(尽管这可能无关紧要),并且
filterOptions
可以具有合理数量的项目,则可以使用 Set 而不是数组。 This is helpful because Set.has
has a computational complexity of O(1)
, compared to Array.includes
, which is O(n)
:这是有用的,因为
Set.has
具有的计算复杂度O(1)
相对于Array.includes
,这是O(n)
const filterOptions = new Set(['Black', 'Green', '10.00', 'Wacky', 'false']); const data = { games: [{ name: 'Game1', color: 'Black', price: '1.00', theme: 'Lucky', licensed: true }, { name: 'Game2', color: 'Pink', price: '1.00', theme: 'Multiple', licensed: true }, { name: 'Game3', color: 'Black', price: '5.00', theme: 'Crossword', licensed: false }, { name: 'Game4', color: 'Green', price: '5.00', theme: 'Lucky', licensed: true }, { name: 'Game5', color: 'Black', price: '10.00', theme: 'Wacky', licensed: false }, { name: 'Game6', color: 'Green', price: '10.00', theme: 'Wacky', licensed: false }, ] } const matchingObjects = data.games.filter( ({ name, ...game }) => Object.values(game).every( value => filterOptions.has(String(value)) ) ); console.log(matchingObjects);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.