按字符串值过滤嵌套对象数组
Filtering an array of nested objects by string value
我正在尝试使用嵌套对象过滤数组,如下所示:
const items = [
{
"id": 1,
"name": "test1",
"subitems": [
{
"id": 2,
"name": "test2",
"subsubitems": [
{
"id": 3,
"name": "test3",
},
{
"id": 4,
"name": "test4",
}
]
}
]
},
{
"id": 10,
"name": "test10",
"subitems": [
{
"id": 20,
"name": "test20",
"subsubitems": [
{
"id": 30,
"name": "test30",
}
]
}
]
}
]
const filteredResults = items.filter((item) =>
item.subitems.some((subitem) =>
subitem.subsubitems.some((subsubitem) =>
subsubitem.name.includes('test3')
)
)
)
console.log(filteredResults)
但过滤不正确,原始数组正在 returned。现在我只是试图在子项级别进行过滤。最终我想要 return 一个数组,其中包含任何级别的任何匹配项。
所以 test2
会 return 一个这样的数组:
[
{
"id": 1,
"name": "test1",
"subitems": [
{
"id": 2,
"name": "test2",
"subsubitems": [
{
"id": 3,
"name": "test3",
},
{
"id": 4,
"name": "test4",
}
]
}
]
}
]
而 test3
会 return 一个这样的数组:
[
{
"id": 1,
"name": "test1",
"subitems": [
{
"id": 2,
"name": "test2",
"subsubitems": [
{
"id": 3,
"name": "test3",
}
]
}
]
},
{
"id": 10,
"name": "test10",
"subitems": [
{
"id": 20,
"name": "test20",
"subsubitems": [
{
"id": 30,
"name": "test30",
}
]
}
]
}
]
并且 test
会 return 一切。
您可以使用一个函数来检查实际级别并搜索子级别,如果子级别有长度,则将实际级别作为结果。
const
filter = childrenKey => o => {
if (o.name === value) return o;
const childrenValues = (o[childrenKey] || []).flatMap(filter('sub' + childrenKey));
return childrenValues.length ? { ...o, [childrenKey]: childrenValues } : [];
},
data = [{ id: 1, name: "test1", subitems: [{ id: 2, name: "test2", subsubitems: [{ id: 3, name: "test3" }, { id: 4, name: "test4" }] }] }, { id: 10, name: "test10", subitems: [{ id: 20, name: "test20", subsubitems: [{ id: 30, name: "test30" }] }] }],
value = 'test3',
result = data.flatMap(filter('subitems'));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
如果我没理解错的话,流程是:
- 如果当前级别的
name
包含搜索值,则将当前级别和所有可用的 subitems
或 subsubitems
数组中的子级包含在内。
- 否则,对
subitems
或 subsubitems
数组中可用的每个项目重复相同的检查,如果有任何结果,则包括当前项目。
我认为以下示例会让您产生这种行为。请注意,在搜索“test2”时,名称为“test3”和“test4”的项目包含在您的问题中。此外,包含“test20”是因为除了 subsubitems
级别外,它还在 subitems
级别进行搜索,并且“test20”包括“test2”。
const items = [
{ id: 1, name: "test1", subitems: [
{ id: 2, name: "test2", subsubitems:[
{ id: 3, name: "test3" },
{ id: 4, name: "test4" }
]}
]},
{ id: 10, name: "test10", subitems: [
{ id: 20, name: "test20", subsubitems: [
{ id: 30, name: "test30"}
]}
]}
];
const deepFilter = (items, value) => items.reduce((arr, cur) => {
if (cur.name.includes(value)) arr.push(cur);
else if (cur.hasOwnProperty('subitems')) {
const subItems = deepFilter(cur.subitems, value);
if (subItems.length) {
cur.subitems = subItems;
arr.push(cur);
}
}
else if (cur.hasOwnProperty('subsubitems')) {
const subSubItems = deepFilter(cur.subsubitems, value);
if (subSubItems.length) {
cur.subsubitems = subSubItems;
arr.push(cur);
}
}
return arr;
}, []);
console.log('test2:');
console.log(deepFilter(items, 'test2'));
console.log('test3:');
console.log(deepFilter(items, 'test3'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
我正在尝试使用嵌套对象过滤数组,如下所示:
const items = [
{
"id": 1,
"name": "test1",
"subitems": [
{
"id": 2,
"name": "test2",
"subsubitems": [
{
"id": 3,
"name": "test3",
},
{
"id": 4,
"name": "test4",
}
]
}
]
},
{
"id": 10,
"name": "test10",
"subitems": [
{
"id": 20,
"name": "test20",
"subsubitems": [
{
"id": 30,
"name": "test30",
}
]
}
]
}
]
const filteredResults = items.filter((item) =>
item.subitems.some((subitem) =>
subitem.subsubitems.some((subsubitem) =>
subsubitem.name.includes('test3')
)
)
)
console.log(filteredResults)
但过滤不正确,原始数组正在 returned。现在我只是试图在子项级别进行过滤。最终我想要 return 一个数组,其中包含任何级别的任何匹配项。
所以 test2
会 return 一个这样的数组:
[
{
"id": 1,
"name": "test1",
"subitems": [
{
"id": 2,
"name": "test2",
"subsubitems": [
{
"id": 3,
"name": "test3",
},
{
"id": 4,
"name": "test4",
}
]
}
]
}
]
而 test3
会 return 一个这样的数组:
[
{
"id": 1,
"name": "test1",
"subitems": [
{
"id": 2,
"name": "test2",
"subsubitems": [
{
"id": 3,
"name": "test3",
}
]
}
]
},
{
"id": 10,
"name": "test10",
"subitems": [
{
"id": 20,
"name": "test20",
"subsubitems": [
{
"id": 30,
"name": "test30",
}
]
}
]
}
]
并且 test
会 return 一切。
您可以使用一个函数来检查实际级别并搜索子级别,如果子级别有长度,则将实际级别作为结果。
const
filter = childrenKey => o => {
if (o.name === value) return o;
const childrenValues = (o[childrenKey] || []).flatMap(filter('sub' + childrenKey));
return childrenValues.length ? { ...o, [childrenKey]: childrenValues } : [];
},
data = [{ id: 1, name: "test1", subitems: [{ id: 2, name: "test2", subsubitems: [{ id: 3, name: "test3" }, { id: 4, name: "test4" }] }] }, { id: 10, name: "test10", subitems: [{ id: 20, name: "test20", subsubitems: [{ id: 30, name: "test30" }] }] }],
value = 'test3',
result = data.flatMap(filter('subitems'));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
如果我没理解错的话,流程是:
- 如果当前级别的
name
包含搜索值,则将当前级别和所有可用的subitems
或subsubitems
数组中的子级包含在内。 - 否则,对
subitems
或subsubitems
数组中可用的每个项目重复相同的检查,如果有任何结果,则包括当前项目。
我认为以下示例会让您产生这种行为。请注意,在搜索“test2”时,名称为“test3”和“test4”的项目包含在您的问题中。此外,包含“test20”是因为除了 subsubitems
级别外,它还在 subitems
级别进行搜索,并且“test20”包括“test2”。
const items = [
{ id: 1, name: "test1", subitems: [
{ id: 2, name: "test2", subsubitems:[
{ id: 3, name: "test3" },
{ id: 4, name: "test4" }
]}
]},
{ id: 10, name: "test10", subitems: [
{ id: 20, name: "test20", subsubitems: [
{ id: 30, name: "test30"}
]}
]}
];
const deepFilter = (items, value) => items.reduce((arr, cur) => {
if (cur.name.includes(value)) arr.push(cur);
else if (cur.hasOwnProperty('subitems')) {
const subItems = deepFilter(cur.subitems, value);
if (subItems.length) {
cur.subitems = subItems;
arr.push(cur);
}
}
else if (cur.hasOwnProperty('subsubitems')) {
const subSubItems = deepFilter(cur.subsubitems, value);
if (subSubItems.length) {
cur.subsubitems = subSubItems;
arr.push(cur);
}
}
return arr;
}, []);
console.log('test2:');
console.log(deepFilter(items, 'test2'));
console.log('test3:');
console.log(deepFilter(items, 'test3'));
.as-console-wrapper { max-height: 100% !important; top: 0; }