[英]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.