2017-07-23 89 views
1

我想過濾具有對象數組內的對象數組。例如,數組中的對象看起來像這樣。更簡單的過濾對象數組對象數組的方法

list=[..., 
    { 
     "types": [ 
      { 
      "slot": 2, 
      "type": 
       { 
        "url": "http://pokeapi.co/api/v2/type/4/", 
        "name": "poison" 
       } 
      }, 
      { 
      "slot": 1, 
      "type": 
       { 
        "url": "http://pokeapi.co/api/v2/type/12/", 
        "name": "grass" 
       } 
      } 
     ], 
     "name": 'bulbasaur' 
    },... 
] 

我目前正在過濾其名稱的列表和類型,如該對象(在this.props.search.search是一個字符串,例如是字符串的例子清單將被調整):

let filtered = this.props.pokemons.filter((pokemon)=>{ 
     return pokemon.name.toLowerCase().indexOf(this.props.search.search.toLocaleLowerCase())!==-1; 
    }) 
    let example = ['fire', 'ice', 'water']; 
    let filteredx= filtered.filter((pokemon)=>{ 
     return pokemon.types.filter((type)=>{ 
      return example.indexOf(type.type.name)!==-1 
     }).length>0 
    }) 

是否有所有過濾器組合成一個而不是調用

array.filter(...).filter(...) 

作爲未來的一個方法,如果添加了更多的過濾器,我擔心它會結束向上看起來像

array.filter(...).filter(...).filter(...).filter(...).filter(...) 

任何幫助,將不勝感激。

+0

考慮使用'const',而不是'let'儘可能。它使您的代碼更具可預測性。 – ideaboxer

回答

1

您可以用&&兩個條件結合起來:

let filteredx = this.props.pokemons.filter(pokemon => 
    pokemon.name.toLowerCase().includes(this.props.search.search.toLocaleLowerCase()) 
    && pokemon.types.some(type => example.includes(type.type.name)) 
) 

注意,你可以在你的條件下使用includessome,並使用您的箭頭功能的表達式語法(不含括號也不return)。

您可以使用其他&&操作員添加更多條件。確保按照最簡單的條件(需要最少工作)的順序放置它們。

+0

謝謝大家的回答,但是這個看起來像是我正在尋找的那個! – Iruss

0

如果數組很小並且性能不是問題;

const arryOfPokemons = [{name: 'name1', type: 'type1'}]; 

function name(pokemon) { return pokemon.name !== 'name' } 

function type(pokemon) { return pokemon.type !== 'type' } 

const result = [name, type].reduce((result, filterFunc) => result.filter(filterFunc), arryOfPokemons); 

否則,您可以嘗試將條件組合成相同的過濾器函數。

0

不是多次過濾,您可以將一個過濾器中的所有過濾條件組合在一起。

而不是做這個的......

let filtered1 = toFilter.filter((element) => { 
    return condition1; 
}); 

let filtered2 = filtered1.filter((element) => { 
    return condition2; 
}); 

... 

let filteredN = filteredN_1.filter((element) => { 
    return conditionN; 
}); 

...你可以在一個單一的過濾器相結合的條件:

let filtered = toFilter.filter((element) => { 
    return condition1 && condition2 && ... && conditionN; 
}); 

如果其中一個條件是很長的,你可以很容易地在一個單獨的函數中抽象它。這也使代碼更具可讀性和可維護性。

let filtered = toFilter.filter((element) => { 
    const condition1 = computeCondition1(arg1, arg2); 
    const condition2 = computeCondition2(arg1); 
    ... 
    const condition3 = computeCondition3(arg2, arg3, arg4); 

    return condition1 && condition2 && ... && conditionN; 
}); 
+0

爲什麼'const'而不是'let'? – ideaboxer

+0

@ideaboxer,很好的觀察。編輯... – ninjin

0

您可以定義一個對象,其中包含您要測試的寵物小精靈列表的每個第一級屬性的屬性。該值將成爲此屬性的「測試邏輯」的謂詞。

const pokemons = [ 
 
    {"name":"poke1","types":[{"type":{"name":"poison"}},{"type":{"name":"grass"}}]}, 
 
    {"name":"poke2","types":[{"type":{"name":"fire"}},{"type":{"name":"grass"}}]}, 
 
    {"name":"poke3","types":[{"type":{"name":"ice"}},{"type":{"name":"water"}}]}, 
 
    {"name":"poke4","types":[{"type":{"name":"ice"}},{"type":{"name":"grass"}}]} 
 
]; 
 

 
const filterOptions = { 
 
    name: (name) => { 
 
    return ["poke1", "poke5"].some(x => x === name); 
 
    }, 
 
    types: (types) => { 
 
    return ["ice", "water"].some(t => types.some(x => t === x.type.name)); 
 
    } 
 
}; 
 

 
function filterList(list, options) { 
 
    return list.filter(pokemon => { 
 
    return Object.keys(filterOptions) 
 
       .some(key => { 
 
        if (key in pokemon) { 
 
        return filterOptions[key](pokemon[key]); 
 
        } 
 
       }); 
 
    }); 
 
} 
 

 
const filtered = filterList(pokemons, filterOptions); 
 
filtered.forEach(p => console.log(JSON.stringify(p)));