簡體   English   中英

如何使用Lodash通過多個潛在屬性過濾對象集合?

[英]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']
}

在這種情況下,我想將集合過濾為以下所有對象:

  • 顏色是紅色或橙色或黃色
  • AND形狀為圓形

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM