繁体   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