繁体   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?

我正在研究过滤功能,该功能可以通过呈现的数据列表进行过滤。 我的目标是能够使用用户选择的过滤器过滤数据对象并返回与所有选定过滤器选项匹配的任何数据对象。

例如,这是一个模拟的选定选项数组:

//This simulates a current filter options array
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
        },
    ]
}

考虑到上面提到的模拟过滤器选项,我希望看到Game5 & Game6 两者都是10.00 ,要么是Black or Green ,都有wacky主题,并且有一个falselicense值。

我的想法是,放弃使用“松散值”数组会更容易,并且可能会创建一个包含所选过滤器选项数组的对象,这些选项数组的属性是我打算比较的属性的名称它反对在数据对象中。

例如:

`const filterOptions = 
  {
    color: ['Black', 'Green'],
    price: ['10.00'],
    theme: ['Wacky'],
    licensed: [false]
  }`

然后,我可以使用Object.keys(filterOptions)类的东西来循环选定的过滤器选项对象。 我唯一的事情是似乎对于每个游戏,我都需要像这样循环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
         })
    })
})

总的来说,对于games.forEach()每次迭代,我似乎需要 2 个内部forEach()循环。 我正在处理的数据对象只返回 5000 多个游戏对象,我觉得这种方法对于如此大的数据数组会非常耗时。

我对我的处理方法感到非常困惑,我担心我会根深蒂固地以某种方式这样做,最终是不够的。 也许我可以在lodash中使用一些东西来帮助做这样的事情? 我偶尔使用过lodash库,但我不确定如何将它应用于具有这么多匹配条件的东西。 所以我的问题是:什么是解决这个问题的聪明方法?

在迭代对象时,检查.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);

只要你能为它们提出一致的规则,“松散”值就不是问题,代码仍然非常简洁。

如果您担心性能(尽管这可能无关紧要),并且filterOptions可以具有合理数量的项目,则可以使用 Set 而不是数组。 这是有用的,因为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