我有一个过滤功能,使用filter
快速搜索数组中的文本:
filtered = filtered.filter((row) => {
return Object.keys(row).some((key) => {
return String(row[key]).toLowerCase().indexOf(this.quickSearch.toLowerCase()) > -1
})
})
这适用于单级数组,但不确定如何调整它以处理未知数量级别的对象数组
{
'name': 'james',
'post': {
'name': 'my favorite teams'
}
}
上面的代码找到james
,没问题,但找不到teams
,因为它不够深入。
当然,我不想对if row[key] == 'post'
之类的内容进行硬编码,因为我将此代码用于多个数据源,并且需要它是动态的。
如何使其适用于多级数组,如上例所示?
答案 0 :(得分:2)
您可以使用递归函数来调用对象和数组的值(使用Object.values
和Array#some
):
const containsDeep = (text) => (value) => {
if(!value) return false;
const valueType = typeof value;
if(valueType === 'string') {
return value.toLowerCase().indexOf(text.toLowerCase()) > -1;
}
if(Array.isArray(value)) {
return value.some(containsDeep(text));
}
if(valueType === 'object') {
return Object.values(value).some(containsDeep(text));
}
return false;
};
const data = [
{
'name': 'bar',
'post': {
'name': 'my favorite teams'
}
},
{
'name': 'fizz',
'posts': [{'name': 'buzz'}]
},
{
'name': 'bla',
'post': {
'name': 'blee',
'comments': [null, {'name': 'bar'}]
}
},
{
'name': 'foo',
'post': {
'name': 'bar'
}
}
];
const result = data.filter(containsDeep('bar'));
console.log(result);
答案 1 :(得分:2)
如果有多个级别,则递归是最佳解决方案:
let searchString = this.quickSearch.toLowerCase(); // do this only once instead of calling toLowerCase over and over again, besides we are using a regular function (not an arrow one) so "this" will be messed up anyways
filtered = filtered.filter(function search(row) { // name the function so we can use recursion (thus we can't use an arrow function)
return Object.keys(row).some((key) => { // ...
if(typeof row[key] === "string") { // if the current property is a string
return row[key].toLowerCase().indexOf(searchString) > -1; // then check if it contains the search string
} else if(row[key] && typeof row[key] === "object") { // oterwise, if it's an object
return search(row[key]); // do a recursive check
}
return false; // return false for any other type (not really necessary as undefined will be returned implicitly)
});
});