我知道有类似的问题,但是到目前为止,没有一个问题可以帮助我-filtering an array of objects from and array of strings依赖于您知道要匹配的键值对,并且与此问题相同{{3} }
说我有一个像这样的对象数组。
let users = [
{
name: 'Steve',
age: 42,
pets: {
dog: 'spike';
},
favouriteFood: 'apples'
},
{
name: 'Steve',
age: 32,
pets null
favouriteFood: 'icecream'
},
{
name: 'Jason',
age: 31,
pets: null
favouriteFood: 'tacos'
},
{
name: 'Jason',
age: 31,
pets: {
cat: 'Jerry'
},
favouriteFood: 'bread'
},
]
现在,我希望能够通过匹配任何对象键中的字符串来过滤用户数组。例如,我想过滤掉名字不是'steve'的任何人-请记住,我可能也想过滤掉不是42岁或者最喜欢的食物不是'苹果'的任何人
filter(term) {
return objects.filter(x => {
for(let key of Object.keys(x)) {
if(typeof(x[key]) === 'object') {
return JSON.stringify(x[key]).toLowerCase().includes(t);
} else {
return x[key].toString().toLowerCase().includes(t);
}
}
});
}
现在此功能有效,但仅适用于一个过滤条件
所以如果我运行filter('steve')
,我会得到
users = [
{
name: 'Steve',
age: 42,
pets: {
dog: 'spike';
},
favouriteFood: 'apples'
},
{
name: 'Steve',
age: 32,
pets null
favouriteFood: 'icecream'
}
]
结果是,但是如果我想过滤掉史蒂夫最喜欢的食物是苹果,那该怎么办?
我尝试如下更新函数,以遍历术语数组并根据数组中的所有字符串进行过滤
所以我尝试过
function filter(terms) {
return term.forEach((t) => {
return objects.filter(x => {
for(let key of Object.keys(x)) {
if(typeof(x[key]) === 'object') {
return JSON.stringify(x[key]).toLowerCase().includes(t);
} else {
return x[key].toString().toLowerCase().includes(t);
}
}
});
});
但是当我运行filter(['steve', 'apples'])
我得到undefined
我想要的结果是
users = [
{
name: 'Steve',
age: 42,
pets: {
dog: 'spike';
},
favouriteFood: 'apples'
}
]
我不确定自己做错了什么或如何解决此功能,以便使其正常工作。
任何帮助将不胜感激。
答案 0 :(得分:5)
根据给定用户的.every
中是否包含所需数组中的Object.values
个值进行过滤:
const filter = arrOfValsNeeded => users.filter(user => {
const vals = Object.values(user).map(val => typeof val === 'string' ? val.toLowerCase() : val);
return arrOfValsNeeded.every(needed => vals.includes(needed.toLowerCase()));
});
let users = [
{
name: 'Steve',
age: 42,
pets: {
dog: 'spike'
},
favouriteFood: 'apples'
},
{
name: 'Steve',
age: 32,
pets: null,
favouriteFood: 'icecream'
},
{
name: 'Jason',
age: 31,
pets: null,
favouriteFood: 'tacos'
},
{
name: 'Jason',
age: 31,
pets: {
cat: 'Jerry'
},
favouriteFood: 'bread'
},
]
console.log(filter(['steve', 'apples']));
或者,如果您需要递归查找所有原始值:
const allPrimitives = obj => {
const primitives = [];
JSON.stringify(obj, (key, val) => {
if (typeof val !== 'object' || val === null) {
primitives.push(typeof val === 'string' ? val.toLowerCase() : val);
}
return val;
});
return primitives;
};
const filter = arrOfValsNeeded => users.filter(user => {
const vals = allPrimitives(user);
return arrOfValsNeeded.every(needed => vals.includes(needed.toLowerCase()));
});
let users = [
{
name: 'Steve',
age: 42,
pets: {
dog: 'spike'
},
favouriteFood: 'apples'
},
{
name: 'Steve',
age: 32,
pets: null,
favouriteFood: 'icecream'
},
{
name: 'Jason',
age: 31,
pets: null,
favouriteFood: 'tacos'
},
{
name: 'Jason',
age: 31,
pets: {
cat: 'Jerry'
},
favouriteFood: 'bread'
},
]
console.log(filter(['steve', 'apples']));
如果还需要部分匹配,请使用vals.some
代替vals.includes
,以便标识子字符串:
const allStrings = obj => {
const strings = [];
JSON.stringify(obj, (key, val) => {
if (typeof val === 'string') {
strings.push(val.toLowerCase());
}
return val;
});
return strings;
};
const filter = arrOfValsNeeded => {
const lowerVals = arrOfValsNeeded.map(str => str.toLowerCase());
return users.filter(user => {
const existingStrings = allStrings(user);
return lowerVals.every(
lowerNeeded => existingStrings.some(
existingString => existingString.includes(lowerNeeded)
)
);
});
};
let users = [
{
name: 'Steve',
age: 42,
pets: {
dog: 'spike'
},
favouriteFood: 'apples'
},
{
name: 'Steve',
age: 32,
pets: null,
favouriteFood: 'icecream'
},
{
name: 'Jason',
age: 31,
pets: null,
favouriteFood: 'tacos'
},
{
name: 'Jason',
age: 31,
pets: {
cat: 'Jerry'
},
favouriteFood: 'bread'
},
]
console.log(filter(['steve', 'apples']));
答案 1 :(得分:1)
对不起,您的回复很晚。我一直试图提出在几乎任何情况下都可以使用的递归代码。最终,我发现了一些非常酷的摘要here,这是我从similar
派生equals
函数的地方,并出于兼容性考虑。
function similar(a, b){
if(a === b){
return true;
}
if(a instanceof Date && b instanceof Date){
return a.getTime() === b.getTime();
}
if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')){
return a === b;
}
if (a === null || a === undefined || b === null || b === undefined || a.prototype !== b.prototype){
return false;
}
return Object.keys(b).every(function(k){
return similar(a[k], b[k]);
});
}
let users = [
{
name: 'Steve',
age: 42,
pets: {
dog: 'spike'
},
favouriteFood: 'apples'
},
{
name: 'Steve',
age: 32,
pets: null,
favouriteFood: 'icecream'
},
{
name: 'Jason',
age: 31,
pets: null,
favouriteFood: 'tacos'
},
{
name: 'Jason',
age: 31,
pets: {
cat: 'Jerry'
},
favouriteFood: 'bread'
}
]
var testObj = {name:'Jason', age: 31, pets:{cat:'Jerry'}};
for(var i=0,u,l=users.length; i<l; i++){
u = users[i];
if(similar(u, testObj)){
console.log('contains testObj');
console.log(u);
}
else if(!similar(u, {pets:null}) && !similar(u, {pets:{dog:'spot'}})){
console.log('not spot');
console.log(u);
}
}
similar
将查看是否有完全匹配的内容不是对象,或者如果是对象,则将考虑到a
和b
是否包含a
b
具有相同深度的属性和值,并且b
不包含a
中不存在的属性。