[英]How to use Lodash to filter a collection of objects by multiple potential properties?
我正在構建一個簡單的篩選UI。 我想使用邏輯AND過濾對象集合,其中對象的匹配取決於任意鍵集中每個對象的多個潛在值。 要過濾的對象如下所示:
collection = [
{
'Kind': 'Instrument',
'Color': 'Orange',
'Shape': 'Square',
'Name': 'Foobar',
},
...
]
用戶的點擊過濾器結果如下所示:
filter = {
'Color': ['Red', 'Orange', 'Yellow'],
'Shape': ['Circle']
}
在這種情況下,我想將集合過濾為以下所有對象:
filter
對象具有任意數量的鍵,因此我不能輕松地編寫這樣的手動過濾器功能:
results = _.filter(collection, item => {
return _.includes(['Red', 'Orange', 'Yellow'], item['Color']) && _.includes(['Circle'], item['Shape'])
})
使用Lodash做到這一點的最干凈的方法是什么? 我是否需要為_.filter
內部collection
每個項目遍歷filter
每個鍵,還是有更好的方法?
PS:我沒有正確的語言來談論我要做的事情。 描述這個問題的最佳關鍵字是什么?
您非常接近:
const collection = [ // Won't be in the output. { 'Kind': 'Instrument', 'Color': 'Orange', 'Shape': 'Square', 'Name': 'Foobar', }, // Will be in the output. { 'Kind': 'Instrument', 'Color': 'Orange', 'Shape': 'Circle', 'Name': 'Foobar', }, // Won't be in the output. { 'Kind': 'Derp', 'Color': 'NoWorky', 'Shape': 'HAHAHAHA', 'Name': 'uWin', } ]; const filter = { 'Color': ['Red', 'Orange', 'Yellow'], 'Shape': ['Circle'] }; const results = _.filter(collection, (item) => { return _.chain(filter) .keys() .reduce((currentBoolean, next) => { console.log(currentBoolean, next, filter[next], item[next]); return _.isNil(item[next]) ? currentBoolean : _.includes(filter[next], item[next]) && currentBoolean; }, true) .value(); // This doesn't work because you're trying to do arbitrary keys. // return _.includes(filter.Color, item.Color) && _.includes(filter.Shape, item.Shape)); }); console.log(results);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
應用一些功能樣式,就像您說的那樣。 希望代碼足夠說明性,否則請讓我知道,我將盡力澄清事情(使用lodashfp會更清晰一些,盡管我認為您沒有使用它)。
希望能幫助到你。
const isValIncluded = item => (value, key) => _.includes(value, _.get(item, key, null)); const isValid = filters => item => _.every(filters, isValIncluded(item)); const filterCol = coll => filters => _.filter(coll, isValid(filters)); const collection = [{ 'Kind': 'Instrument', 'Color': 'Orange', 'Shape': 'Square', 'Name': 'Foobar', }, { 'Kind': 'Instrument', 'Color': 'Orange', 'Shape': 'Circle', 'Name': 'Foobar', }, { 'Kind': 'XXX', 'Color': 'YYY', 'Shape': 'ZZZ', 'Name': 'FFF', }, { 'Kind': 'Instrument', 'Color': 'Red', 'Shape': 'Circle', 'Name': 'Foobar', } ]; const filters = { 'Color': ['Red', 'Orange', 'Yellow'], 'Shape': ['Circle'] }; console.log(filterCol(collection)(filters));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
您可以簡化使用
results = _.filter(collection, item => item.Shape==='Circle' && _.includes(['Red', 'Orange', 'Yellow'], item.Color));
通過在此處不同地命名filter
對象來避免混淆可能是一個好主意。
這將適用於項目列表,在該列表中,您要過濾的namedProperty是“ doorColour”之類的字符串,或者是表示給定Property的路徑的字符串數組,例如['town','street','doorColour']嵌套在項目上的值是town.street.doorColour。
它還可以過濾多個值,因此您只需要傳入表示要保留的字符串值的子字符串數組即可,它將保留具有字符串值的項目,該字符串值包含在substrings數組中的任何子字符串。
最終參數“ includes”可確保您保留這些值(如果將其設置為false),它將排除這些值並保留那些沒有在子字符串數組中指定的值的值。
import { flatMap, path } from 'lodash/fp';
const filteredListForItemsIncludingSubstringsOnAGivenProperty = (items, givenProperty, substrings, including=true) => flatMap((item) =>
substrings.find((substring) => path(givenProperty)(item) && path(givenProperty)(item).includes(substring))
? including
? [item]
: []
: including
? []
: [item])(items);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.