如何从嵌套数据结构中检索基于谓词/条件的特定 属性 值的平面数组?
How do I retrieve from a nested data structure a flat array of specific property values based on a predicate / condition?
我有这个对象数组
[{
id: 1,
checked: true,
subChild: [{
id: 11,
checked: true
}]
}, {
id: 2,
checked: true,
subChild: [{
id: 22,
checked: false
}]
}, {
id: 3,
checked: false,
subChild: [{
id: 33,
checked: true
}]
}]
是否有任何库可以根据项目的 checked
属性 获取项目的 id
值?我可以通过 filter
和 find
迭代数据结构,但这需要大量的手动工作; ...想象我有另一层嵌套对象数组。
所提供示例数据的预期输出为 [1, 11, 2, 33]
。
我会这样做。将 subChild
数组获取到父数组。这在技术上以自定义方式展平数组,然后对此进行过滤。
const subChildren = [];
const final = [
...arr.map(a => {
subChildren.push(a.subChild);
delete a.subChild;
return a;
}),
...subChildren.flat()
];
console.log(final);
这就是代码,我将通过使用过滤器使其变得更好。
final.filter(f => f.checked);
这将给我包含对象的数组。现在我只需要将它转换为 id
s.
final.filter(f => f.checked).map(f => f.id);
这将给我所需的答案:
[1, 2, 11, 33]
这是完整的片段:
const arr = [
{
id: 1,
checked: true,
subChild: [
{
id: 11,
checked: true
}
]
},
{
id: 2,
checked: true,
subChild: [
{
id: 22,
checked: false
}
]
},
{
id: 3,
checked: false,
subChild: [
{
id: 33,
checked: true
}
]
}
];
const subChildren = [];
const final = [
...arr.map(a => {
subChildren.push(a.subChild);
delete a.subChild;
return a;
}),
...subChildren.flat()
];
console.log(final.filter(f => f.checked).map(f => f.id));
您可以执行 flatMap
将 subChild
对象带到父数组,然后 filter
基于 checked
属性 并执行最后的 map
得到 id
s.
const items = [
{
id: 1,
checked: true,
subChild: [
{
id: 11,
checked: true,
},
],
},
{
id: 2,
checked: true,
subChild: [
{
id: 22,
checked: false,
},
],
},
{
id: 3,
checked: false,
subChild: [
{
id: 33,
checked: true,
},
],
},
];
let result = items
.flatMap(({ subChild, ...item }) => [item, ...subChild])
.filter((item) => item.checked)
.map((item) => item.id);
console.log(result)
编辑由于 OP 的句子...
"imagine I have another level of nested array of object."
根据我上面的评论...
@AliciaY ... "imagine I have another level of nested array of object." ... Does the OP ask for a recursive approach which is capable of processing deeper nested structures of the form [{ id: 1, checked: true, subChild: [{ id: 11, checked: true, subChild: [{ id: 111, checked: true/*, subChild: [ ... ] */ }] }] }
?
这个 scenario/case 通过我第一个(现在是下面)提供的 reduce
和 concat
唯一方法的递归实现得到了最好的覆盖。
function collectCheckedItemIdRecursively(
result,
{ id, checked, subChild = [] },
) {
return result.concat(
(checked && id || []),
subChild
.reduce(collectCheckedItemIdRecursively, [])
);
}
const sampleData = [{
id: 1, checked: true,
subChild: [{
id: 11, checked: true,
subChild: [{
id: 111, checked: false,
subChild: [{
id: 1111, checked: true,
}],
}, {
id: 112, checked: true,
subChild: [],
}],
}],
}, {
id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];
console.log(
'recursively implemented `reduce` and `concat` only approach ...',
sampleData
.reduce(collectCheckedItemIdRecursively, [])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
编辑...对于 OP 最初提供的 2 级嵌套数据结构,我保留了之前提供的方法...
OP 的 title/subject
shortcut to retrieve array of object property in javascript
没有捷径但是不同approaches/strategies喜欢...
仅 -
-
-
flatMap
、filter
和 map
与 rest parameter syntax and spread syntax.
const sampleData = [{
id: 1, checked: true, subChild: [{ id: 11, checked: true }],
}, {
id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];
console.log(
'nested `reduce` and `concat` twice ...',
sampleData
.reduce((result, { id, checked, subChild }) =>
result.concat(
(checked && id || []),
subChild
.reduce((arr, { id, checked }) =>
arr.concat(checked && id || []), []
)
), [])
);
console.log(
'`reduce` and `concat` with nested `filter` and `map` ...',
sampleData
.reduce((result, { id, checked, subChild }) =>
result.concat(
(checked && id || []),
subChild
.filter(({ checked }) => checked)
.map(({ id }) => id)
), [])
);
console.log(
'`flatMap` and `flat` with nested `filter` and `map` ...',
sampleData
.flatMap(({ id, checked, subChild }) => [
(checked && id || []),
subChild
.filter(({ checked }) => checked)
.map(({ id }) => id)
].flat())
);
console.log(
'`flatMap`, `filter` and `map` with rest parameter- and spread-syntax ...',
sampleData
.flatMap(({ subChild, ...rest }) => [rest, ...subChild])
.filter(({ checked }) => checked)
.map(({ id }) => id)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
const sampleData = [{
id: 1, checked: true,
subChild: [{
id: 11, checked: true,
subChild: [{
id: 111, checked: false,
subChild: [{
id: 1111, checked: true,
}],
}, {
id: 112, checked: true,
subChild: [],
}],
}],
}, {
id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];
// 1. flatMap the items recursively
const flatFunc = ({ subChild, ...item }) => [item].concat(
Array.isArray(subChild) ? subChild.flatMap(flatFunc) : []
);
const flattenArray = sampleData.flatMap(flatFunc);
// 2. filter and map to get the result
const checkedIDs = flattenArray
.filter(item => item.checked)
.map(item => item.id);
console.log({ checkedIDs, flattenArray });
.as-console-wrapper { min-height: 100%!important; top: 0; }
这应该适合你!!!
const array = [
{
id: 1,
checked: true,
subChild: [
{
id: 11,
checked: true,
},
],
},
{
id: 2,
checked: true,
subChild: [
{
id: 22,
checked: false,
},
],
},
{
id: 3,
checked: false,
subChild: [
{
id: 33,
checked: true,
},
],
},
];
let result = array
.flatMap(({ subChild, ...item }) => [item, ...subChild])
.filter((item) => item.checked)
.map((item) => item.id);
我有这个对象数组
[{
id: 1,
checked: true,
subChild: [{
id: 11,
checked: true
}]
}, {
id: 2,
checked: true,
subChild: [{
id: 22,
checked: false
}]
}, {
id: 3,
checked: false,
subChild: [{
id: 33,
checked: true
}]
}]
是否有任何库可以根据项目的 checked
属性 获取项目的 id
值?我可以通过 filter
和 find
迭代数据结构,但这需要大量的手动工作; ...想象我有另一层嵌套对象数组。
所提供示例数据的预期输出为 [1, 11, 2, 33]
。
我会这样做。将 subChild
数组获取到父数组。这在技术上以自定义方式展平数组,然后对此进行过滤。
const subChildren = [];
const final = [
...arr.map(a => {
subChildren.push(a.subChild);
delete a.subChild;
return a;
}),
...subChildren.flat()
];
console.log(final);
这就是代码,我将通过使用过滤器使其变得更好。
final.filter(f => f.checked);
这将给我包含对象的数组。现在我只需要将它转换为 id
s.
final.filter(f => f.checked).map(f => f.id);
这将给我所需的答案:
[1, 2, 11, 33]
这是完整的片段:
const arr = [
{
id: 1,
checked: true,
subChild: [
{
id: 11,
checked: true
}
]
},
{
id: 2,
checked: true,
subChild: [
{
id: 22,
checked: false
}
]
},
{
id: 3,
checked: false,
subChild: [
{
id: 33,
checked: true
}
]
}
];
const subChildren = [];
const final = [
...arr.map(a => {
subChildren.push(a.subChild);
delete a.subChild;
return a;
}),
...subChildren.flat()
];
console.log(final.filter(f => f.checked).map(f => f.id));
您可以执行 flatMap
将 subChild
对象带到父数组,然后 filter
基于 checked
属性 并执行最后的 map
得到 id
s.
const items = [
{
id: 1,
checked: true,
subChild: [
{
id: 11,
checked: true,
},
],
},
{
id: 2,
checked: true,
subChild: [
{
id: 22,
checked: false,
},
],
},
{
id: 3,
checked: false,
subChild: [
{
id: 33,
checked: true,
},
],
},
];
let result = items
.flatMap(({ subChild, ...item }) => [item, ...subChild])
.filter((item) => item.checked)
.map((item) => item.id);
console.log(result)
编辑由于 OP 的句子...
"imagine I have another level of nested array of object."
根据我上面的评论...
@AliciaY ... "imagine I have another level of nested array of object." ... Does the OP ask for a recursive approach which is capable of processing deeper nested structures of the form
[{ id: 1, checked: true, subChild: [{ id: 11, checked: true, subChild: [{ id: 111, checked: true/*, subChild: [ ... ] */ }] }] }
?
这个 scenario/case 通过我第一个(现在是下面)提供的 reduce
和 concat
唯一方法的递归实现得到了最好的覆盖。
function collectCheckedItemIdRecursively(
result,
{ id, checked, subChild = [] },
) {
return result.concat(
(checked && id || []),
subChild
.reduce(collectCheckedItemIdRecursively, [])
);
}
const sampleData = [{
id: 1, checked: true,
subChild: [{
id: 11, checked: true,
subChild: [{
id: 111, checked: false,
subChild: [{
id: 1111, checked: true,
}],
}, {
id: 112, checked: true,
subChild: [],
}],
}],
}, {
id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];
console.log(
'recursively implemented `reduce` and `concat` only approach ...',
sampleData
.reduce(collectCheckedItemIdRecursively, [])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
编辑...对于 OP 最初提供的 2 级嵌套数据结构,我保留了之前提供的方法...
OP 的 title/subject
shortcut to retrieve array of object property in javascript
没有捷径但是不同approaches/strategies喜欢...
-
仅
flatMap
、filter
和map
与 rest parameter syntax and spread syntax.
const sampleData = [{
id: 1, checked: true, subChild: [{ id: 11, checked: true }],
}, {
id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];
console.log(
'nested `reduce` and `concat` twice ...',
sampleData
.reduce((result, { id, checked, subChild }) =>
result.concat(
(checked && id || []),
subChild
.reduce((arr, { id, checked }) =>
arr.concat(checked && id || []), []
)
), [])
);
console.log(
'`reduce` and `concat` with nested `filter` and `map` ...',
sampleData
.reduce((result, { id, checked, subChild }) =>
result.concat(
(checked && id || []),
subChild
.filter(({ checked }) => checked)
.map(({ id }) => id)
), [])
);
console.log(
'`flatMap` and `flat` with nested `filter` and `map` ...',
sampleData
.flatMap(({ id, checked, subChild }) => [
(checked && id || []),
subChild
.filter(({ checked }) => checked)
.map(({ id }) => id)
].flat())
);
console.log(
'`flatMap`, `filter` and `map` with rest parameter- and spread-syntax ...',
sampleData
.flatMap(({ subChild, ...rest }) => [rest, ...subChild])
.filter(({ checked }) => checked)
.map(({ id }) => id)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
const sampleData = [{
id: 1, checked: true,
subChild: [{
id: 11, checked: true,
subChild: [{
id: 111, checked: false,
subChild: [{
id: 1111, checked: true,
}],
}, {
id: 112, checked: true,
subChild: [],
}],
}],
}, {
id: 2, checked: true, subChild: [{ id: 22, checked: false }],
}, {
id: 3, checked: false, subChild: [{ id: 33, checked: true }],
}];
// 1. flatMap the items recursively
const flatFunc = ({ subChild, ...item }) => [item].concat(
Array.isArray(subChild) ? subChild.flatMap(flatFunc) : []
);
const flattenArray = sampleData.flatMap(flatFunc);
// 2. filter and map to get the result
const checkedIDs = flattenArray
.filter(item => item.checked)
.map(item => item.id);
console.log({ checkedIDs, flattenArray });
.as-console-wrapper { min-height: 100%!important; top: 0; }
这应该适合你!!!
const array = [
{
id: 1,
checked: true,
subChild: [
{
id: 11,
checked: true,
},
],
},
{
id: 2,
checked: true,
subChild: [
{
id: 22,
checked: false,
},
],
},
{
id: 3,
checked: false,
subChild: [
{
id: 33,
checked: true,
},
],
},
];
let result = array
.flatMap(({ subChild, ...item }) => [item, ...subChild])
.filter((item) => item.checked)
.map((item) => item.id);