[英]How do I retrieve from a nested data structure a flat array of specific property values based on a predicate / condition?
I have this array of objects我有这个对象数组
[{
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
}]
}]
Is there any lib to get an item's id
value based on its checked
property?是否有任何库可以根据其checked
的属性获取项目的id
值? I could iterate the data-structure by filter
and find
but it would be a lot of manual work;我可以通过filter
迭代数据结构并find
,但这将是很多手动工作; ... imagine I have another level of nested arrays of objects. ...想象一下我有另一层嵌套的对象数组。
The expected output for the provided sample data is [1, 11, 2, 33]
.提供的样本数据的预期输出是[1, 11, 2, 33]
。
You could do a flatMap
to bring subChild
objects to the parent array, then filter
based on checked
property and do a final map
to get the id
s.您可以做一个flatMap
将subChild
对象带到父数组,然后根据checked
的属性进行filter
并做一个最终的map
来获取id
。
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)
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; }
I will do this way.我会这样做。 Get the subChild
arrays to the parent one.将subChild
数组传递给父数组。 That's technically flattening the array in a custom way and then do a filter on this.这在技术上以自定义方式展平阵列,然后对此进行过滤。
const subChildren = [];
const final = [
...arr.map(a => {
subChildren.push(a.subChild);
delete a.subChild;
return a;
}),
...subChildren.flat()
];
console.log(final);
Now that's the code that I'll make it even more better by using a filter.现在这就是我将通过使用过滤器使它变得更好的代码。
final.filter(f => f.checked);
This will give me the array with objects.这将为我提供带有对象的数组。 Now I just need to transform it to just id
s.现在我只需要将它转换为id
。
final.filter(f => f.checked).map(f => f.id);
This will give me the required answer of:这将为我提供以下所需的答案:
[1, 2, 11, 33]
Here's the full snippet:这是完整的片段:
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));
EDIT due to the OP's sentence ...编辑由于OP的句子...
"imagine I have another level of nested array of object." “想象一下我有另一层嵌套的对象数组。”
From my above comment ...从我上面的评论...
@AliciaY ... "imagine I have another level of nested array of object." @AliciaY ... “想象一下我有另一层嵌套的对象数组。” ... 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: [ ... ] */ }] }] }
? ... OP 是否要求一种递归方法,该方法能够处理形式为[{ id: 1, checked: true, subChild: [{ id: 11, checked: true, subChild: [{ id: 111, checked: true/*, subChild: [ ... ] */ }] }] }
?
This scenario/case gets covered best by a recursive implementation of my firstly (and now beneath) provided reduce
and concat
only approach.我首先(现在在下面)提供的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; }
Edit ... for the 2 level nested data structure like provided originally by the OP, I leave my before provided approaches ...编辑...对于像 OP 最初提供的 2 级嵌套数据结构,我保留之前提供的方法...
OP's title/subject OP的标题/主题
shortcut to retrieve array of object property in javascript在 javascript 中检索对象属性数组的快捷方式
There are no shortcuts but different approaches/strategies like ...没有捷径,但有不同的方法/策略,例如...
reduce
and concat
only, but twice (once nested),仅reduce
和concat
,但两次(一次嵌套),
reduce
and concat
with nested filter
and map
,使用嵌套filter
和map
reduce
和concat
,
flatMap
and flat
with nested filter
and map
, flatMap
和flat
带有嵌套filter
和map
,
flatMap
, filter
and map
with rest parameter syntax and spread syntax . flatMap
, filter
和map
与rest 参数语法和传播语法。
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; }
This should work for you !!!这应该适合你!
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.