簡體   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