我正在建立一个简单的过滤用户界面。我想使用逻辑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
中的每个密钥?还是有更好的方式?
P.S。我没有正确的语言来谈论我正在尝试做的事情。描述这个问题的最佳关键词是什么?
答案 0 :(得分:1)
你非常接近:
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>
&#13;
答案 1 :(得分:1)
应用一些功能风格,我只是在你说的时候做。希望代码足够解释,否则请告诉我,我会尝试澄清事情(尽管我认为你没有使用它,但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>
答案 2 :(得分:0)
您可以简化使用
results = _.filter(collection, item => item.Shape==='Circle' && _.includes(['Red', 'Orange', 'Yellow'], item.Color));
通过在此处以不同方式命名filter
对象来避免混淆可能是一个好主意。
答案 3 :(得分:0)
这将适用于要过滤给定属性的项目列表,该属性是“ doorColour”之类的字符串,还是表示给定属性路径的字符串数组,例如[“ town”,“ street”,“ doorColour” ']表示嵌套在项上的值为town.street.doorColour。
它还可以过滤多个值,因此您只需要传入表示要保留的字符串值的子字符串数组即可,它将保留具有字符串值的项目,该字符串值包含在substrings数组中的任何子字符串。
如果将其设置为false,则最终参数'includes'可确保保留这些值,它将排除这些值并保留不具有您在子字符串数组中指定的任何值的
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);