var persons = [
{ Color: "Gold", Location: ["Down"] },
{ Color: "Silver", Location: ["Up", "Down"] },
{ Color: "Silver", Location: ["Up"] }
];
var criteria = [
{ Field: "Color", Values: ["Silver"] },
{ Field: "Location", Values: ["Up", "Down"] }
];
此处字段颜色的类型为String,而Location是一个数组。 我有人,然后有一个过滤标准。我需要一个输出,以便过滤器中选择的所有值都需要与数据匹配。因此,在提供的数据中,如果记录中有Silver,Up和Down,则只有那些记录可见。 (注意AND参数,任何地方都没有OR条件。)
所以输出将是:
{ Color: "Silver", Location: ["Up", "Down"] }
现在,如果过滤条件是:
var criteria = [
{ Field: "Color", Values: ["Silver"] },
{ Field: "Location", Values: ["Up"] }
];
输出将是:
{ Color: "Silver", Location: ["Up", "Down"] },
{ Color: "Silver", Location: ["Up"] }
所以你看到过滤器中的所有值都应与记录匹配。
答案 0 :(得分:0)
我将问题分解为单独的功能。它比你的解决方案更冗长,但我确实认为它更具可读性。
另外:它确实有用。
var persons = [
{ Color: "Gold", Location: ["Down"] },
{ Color: "Silver", Location: ["Up", "Down"] },
{ Color: "Silver", Location: ["Up"] }
];
var criteria = [
{ Field: "Color", Values: ["Silver"] },
{ Field: "Location", Values: ["Up", "Down"] }
];
const arraysEqual = (arr1, arr2) => {
// Very simple array comparison.
if (arr1.length !== arr2.length) return false;
arr1 = arr1.sort();
arr2 = arr2.sort();
for(let i=0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) return false;
}
return true;
};
let result = persons.filter(person => {
// All criteria must match.
for (let criterium of criteria) {
if (criterium.Field === 'Color') {
if (person.Color !== criterium.Values[0]) return false;
}
if (criterium.Field === 'Location') {
if (!arraysEqual(person.Location, criterium.Values)) return false;
}
}
// We didn't *not* match for anything, so we matched!
return true;
});
console.log(result);
/*
{ Color: "Silver", Location: ["Down", "Up"] }
*/
有关正在运行的示例,请参阅https://repl.it/@niels_bom/GoldenIdealMicrobsd。
答案 1 :(得分:0)
在第三次编辑之后,现在我清楚你想要什么 - 将数组作为另一个的子集。
var result = persons.filter(function (person) {
return criteria.every(function (c) {
var value = person[c.Field];
if (typeof value === 'object') {
return c.Values.length<=value.length &&
c.Values.every(function(v,i){return value.includes(v) ;});
}
else
return c.Values.indexOf(value) > -1;
})
})
我还更新了你的jsfiddle:https://jsfiddle.net/gzL42dna/1/
答案 2 :(得分:0)
我相信这有效。使用Set
对部分匹配有很大帮助。如果您想要解释代码,请告诉我。
var persons = [
{ Color: "Gold", Location: ["Down"] },
{ Color: "Silver", Location: ["Up", "Down"] },
{ Color: "Silver", Location: ["Up"] }
];
var criteria = [
{ Field: "Color", Values: ["Silver"] },
{ Field: "Location", Values: ["Up", "Down"] }
];
console.log(match(persons, criteria));
function match(persons, criteria) {
let personMatches = [...persons]
for (let i=0; i < criteria.length; i++) {
let {Field, Values} = criteria[i]
personMatches = personMatches.filter(obj => {
if (Array.isArray(obj[Field])) {
return hasMatches(obj[Field], Values)
} else {
return Values.includes(obj[Field])
}
})
}
return personMatches
}
function hasMatches(arr1, criteria) {
let criteriaSet = new Set(criteria)
let personsSet = new Set(arr1)
for (let el of criteriaSet) {
if (!personsSet.has(el)) return false
}
return true
}