如何基于两个过滤器过滤对象数组



所以,我有一个对象数组:

const myArr = [{
name: 'A',
type: 1,
subtype: 1
},
{
name: 'B',
type: 1,
subtype: 2
},
{
name: 'C',
type: 2,
subtype: 3
},
{
name: 'D',
type: 3,
subtype: 1,
}];

然后我有两个变量,每个变量都有一个ID。它们是typeIdsubtypeId。它们可以是与上面数组上的类型和子类型匹配的数值,也可以是-1,意思是";全部";。

因此,我将展示一些情况以及过滤器应该返回的内容:

type: 1 | subtype: 1 --> A
type: -1 | subtype: -1 --> ABCD
type: 1 | subtype: -1 --> AB
type: 2 | subtype: 3 --> C
type: 2 | subtype: 2 --> nothing
type: 3 | subtype: 1 --> D

你明白了。

const filteredData = data.filter(item => {
const { typeId, subtypeId } = getCurrentFilterIds();
if(typeId === -1) return true;
if(typeId !== -1){
if(subtypeId === -1) return item.type === typeId;
if(subtypeId !== -1) return item.type === typeId && item.subtype === subtypeId;
}
});

我想出了这个函数,但也许还有更好的方法?

如注释中所述,您不希望为列表中的每个项调用getCurrentFilterIds((。所以这应该移到过滤器功能之外。

你的if有点多余,没有必要。您可以使用if-else。但在这种情况下,如果第一个语句为true,则返回一个值,因此也不需要else语句。所以你可以简单地做:

const { typeId, subtypeId } = getCurrentFilterIds();
const filteredData = data.filter(item => {
if (typeId === -1) return true;
if (subtypeId === -1) return item.type === typeId;
return item.type === typeId && item.subtype === subtypeId;
});

你甚至可以更进一步,在一行中返回结果,去掉所有的if。

const { typeId, subtypeId } = getCurrentFilterIds();
const filteredData = data.filter(item => {
return (typeId === -1) || ((item.type === typeId) && (subtypeId === -1 || item.subtype === subtypeId));
});

您可以直接将条件作为表达式,而不是使用if语句。

const
filter = (array, typeId, subtypeId) => array.filter(o =>
typeId === -1 ||
o.type === typeId && (subtypeId === -1 || o.subtype === subtypeId)
),
data = [{ name: 'A', type: 1, subtype: 1 }, { name: 'B', type: 1, subtype: 2 }, { name: 'C', type: 2, subtype: 3 }, { name: 'D', type: 3, subtype: 1 }];

console.log(filter(data, 1, 1));   // A
console.log(filter(data, -1, -1)); // A B C D
console.log(filter(data, 1, -1));  // A B
console.log(filter(data, 2, 3));   // C
console.log(filter(data, 2, 2));   // []
console.log(filter(data, 3, 1));   // D
.as-console-wrapper { max-height: 100% !important; top: 0; }

对属性的检查与对给定x:的typesubtype的检查相同

  • 如果x为-1,则任何属性值都可以
  • 否则,属性值必须等于x

所以我们可以用将其正式化

const propCheck = (k, x) => o => x === -1 ? true : o[k] === x;
//                 ^  ^     ^  
//                 1  2     3
// 1: property name e.g. 'type' or 'subtype'
// 2: x e.g. -1 or 2
// 3: the object to read the property from

我们可以编写一个and函数,它先取两个函数,然后取一个值,将两个函数都应用于它,如果两者都应用了,则返回true:

const and = (f, g) => x => f(x) && g(x);

获取您的typeIdsubtypeId,并将它们传递给相应的propCheck调用。例如

myArr.filter(and(propCheck('type', 2), propCheck('subtype', 3)));
//=> [{name: "C", type: 2, subtype: 3}]
myArr.filter(and(propCheck('type', 2), propCheck('subtype', 2)));
//=> []
myArr.filter(and(propCheck('type', 1), propCheck('subtype', -1)));
//=> [ {name: "A", type: 1, subtype: 1}
//=> , {name: "B", type: 1, subtype: 2}]

最新更新