我有2个数组。一个包含这样的数据。
[{_id:123, Name: Mike, City: London},
{_id:456, Name: John, City: New York}]
另一个具有这样查询的数组。
[{fieldName: Name, operator: ===, value: Mike, logicalOperator: ||},
{fieldName: City, operator: !==, value: London, logicalOperator: ||},]
我们如何用第二个过滤第一个数组。
类似
data.filter(item => query.map(q => item.query.fieldName q.operator q.value)
答案 0 :(得分:2)
您可以使用函数来表示比较操作:
[{
fieldName: "Name",
operator: (a, b) => a === b,
value: "Mike",
logicalOperator: (a, b) => a || b,
}, {
fieldName: "City",
operator: (a, b) => a !== b,
value: "London",
logicalOperator: (a, b) => a || b
}]
然后就这么简单:
data.filter(item => query.reduce((acc, q) => q.locicalOperator(
acc,
q.operator(item[q.fieldName], q.value)
), true);
答案 1 :(得分:0)
您可以检查logicalOperator
并使用some
或every
并使用操作数和运算符过滤数组。
function getFilter(filter) {
var op = {
'&&': (a, b) => a && b,
'||': (a, b) => a || b,
'!==': (a, b) => a !== b,
'===': (a, b) => a === b,
'<>': (a, b) => a !== b,
'>=': (a, b) => a >= b,
// 'startsWith': (a, b) => a.startsWith(b), // see default example below
// 'endsWith': (a, b) => a.endsWith(b),
// 'includes': (a, b) => a.includes(b),
default: k => (a, b) => a[k](b) // works for any method
}, // with this pattern
fn = Array.prototype.reduce.bind(filter);
return o => fn((a, { fieldName, operator, value, logicalOperator }, i) => {
var b = (op[operator] || op.default(operator))(o[fieldName], value)
if (!i) return b;
return op[logicalOperator](a, b);
}, undefined);
}
var data = [{ _id: 123, Name: 'Mike', City: 'London' }, { _id: 456, Name: 'John', City: 'New York' }],
filter = [{ fieldName: 'Name', operator: '===', value: 'Mike', logicalOperator: '||' }, { fieldName: 'City', operator: '!==', value: 'London', logicalOperator: '||' }],
result = data.filter(getFilter(filter))
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 2 :(得分:0)
我有点偏离主题,但我想分享另一种使用prefix notation编写查询的方式。
operators = {
"has" : function (v) { return this.hasOwnProperty(v); },
"var" : function (v) { return this[v]; },
"and" : (a, b) => a && b,
"or" : (a, b) => a || b,
"eq" : (a, b) => a === b
};
data = [
{ id : 789, name : "London", city : "London" },
{ id : 123, name : "John", city : "London" },
{ id : 234, name : "Mike", city : "London" },
{ id : 345, name : "John", city : "New York" },
{ id : 456, name : "Jack", city : "New York" },
{ id : 567, name : "James", city : "New York" },
{ id : 678, key : "value" }
];
queries = [
"key === \"value\"", [
"EQ", "VAR", "key", "value"
],
"name === \"John\"", [
"EQ", "VAR", "name", "John"
],
"name === city", [
"AND",
"AND", "HAS", "name", "HAS", "city",
"EQ", "VAR", "name", "VAR", "city"
],
"name === \"John\" || city === \"London\"", [
"OR",
"EQ", "VAR", "name", "John",
"EQ", "VAR", "city", "London"
],
"id === 234 || name === \"John\" && city === \"New York\"", [
"OR",
"EQ", "VAR", "id", 234,
"AND",
"EQ", "VAR", "name", "John",
"EQ", "VAR", "city", "New York"
],
"city === \"New York\" && (name === \"John\" || name === \"James\")", [
"AND",
"EQ", "VAR", "city", "New York",
"OR",
"EQ", "VAR", "name", "John",
"EQ", "VAR", "name", "James"
]
];
for (i = 0; i < queries.length; i += 2) {
console.log(queries[i]);
console.log(data.filter(
(query => item => evaluate.call(item, query))(queries[i + 1])
).map(function (x) {
return JSON.stringify(x);
}).join("\n"));
}
function evaluate (expr) {
var i, j, op, args, stack = [];
for (i = expr.length - 1; i >= 0; i--) {
op = typeof expr[i] !== "string" ? undefined : (
operators[expr[i].toLowerCase()]
);
if (op === undefined) {
stack.push(expr[i]);
} else {
args = new Array(op.length);
for (j = 0; j < op.length; j++) {
args[j] = stack.pop();
}
stack.push(op.apply(this, args));
}
}
return stack.pop();
}