简体   繁体   English

Javascript - 当对象的属性值与选项数组中的所有值匹配时,遍历一组选项并返回一个对象?

[英]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主题,并且有一个falselicense值。

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.

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