objects 的递归数组追加 属性 children 计数
Recursive array of objects to append property children count
我需要递归循环遍历 object 的数组,每个 object object 都有一个 属性 label
需要修改为包括 children
计数。
看看这个例子:
const nodes = [{
value: 'World',
label: 'World',
children: [{
label: 'Europe',
value: 'Europe',
children: [
{
label: 'Albania',
value: 'AL'
},
{
label: 'BeNeLux',
value: 'BeNeLux',
children: [
{
label: 'The Netherlands',
value: 'NL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Luxembourg',
value: 'LU'
}
]
}
]
}]
}]
预期输出为:
const expectedOutput = [{
value: 'World',
label: 'World (4)',
children: [{
label: 'Europe (4)',
value: 'Europe',
children: [
{
label: 'Albania',
value: 'AL'
},
{
label: 'BeNeLux (3)',
value: 'BeNeLux',
children: [
{
label: 'The Netherlands',
value: 'NL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Luxembourg',
value: 'LU'
}
]
}
]
}]
}]
这就是我现在所做的工作,但它无法正常工作,因为如上文 expectedOutput
所述,Europe
的标签将是 Europe (4)
而我的版本计数 Europe (2)
因为它忽略了欧洲内部的 children。
export const getSortedNodesWithChildrenCountLabel = nodes => {
return nodes
.reduce(function f (output, node) {
if (node?.children) {
node.label += ` (${node.children.length})`
node.children = node.children
.reduce(f, [])
}
output.push(node)
return output
}, [])
}
您可以采用递归方法并从子项中获取计数并更新 label
。
这种方法会改变数据。
function update(nodes) {
return nodes.reduce((count, node) => {
if (node.children) {
var subcount = update(node.children);
node.label += ` (${subcount})`;
return count + subcount;
}
return count + 1;
}, 0);
}
const nodes = [{ value: 'World', label: 'World', children: [{ label: 'Europe', value: 'Europe', children: [{ label: 'Albania', value: 'AL' }, { label: 'BeNeLux', value: 'BeNeLux', children: [{ label: 'The Netherlands', value: 'NL' }, { label: 'Belgium', value: 'BE' }, { label: 'Luxembourg', value: 'LU' }] }] }] }];
update(nodes);
console.log(nodes);
.as-console-wrapper { max-height: 100% !important; top: 0; }
一个非变异版本,它通过外部调用的对象获取计数。
function fn(count = { count: 0 }) {
return function ({ value, label, children }) {
var sub = { count: 0 };
if (children) {
children = children.map(fn(sub)),
label += ` (${sub.count})`;
count.count += sub.count;
return { value, label, children };
}
count.count++;
return { value, label };
};
}
const
nodes = [{ value: 'World', label: 'World', children: [{ label: 'Europe', value: 'Europe', children: [{ label: 'Albania', value: 'AL' }, { label: 'BeNeLux', value: 'BeNeLux', children: [{ label: 'The Netherlands', value: 'NL' }, { label: 'Belgium', value: 'BE' }, { label: 'Luxembourg', value: 'LU' }] }] }] }],
withCount = nodes.map(fn());
console.log(withCount);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以将儿童计数分解为单独的递归函数:
const nodes = [{
value: 'World',
label: 'World',
children: [{
label: 'Europe',
value: 'Europe',
children: [
{
label: 'Albania',
value: 'AL'
},
{
label: 'BeNeLux',
value: 'BeNeLux',
children: [
{
label: 'The Netherlands',
value: 'NL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Luxembourg',
value: 'LU'
}
]
}
]
}]
}]
const getChildrenCount = (node, count = 0) => {
if (!node.children) {
return 1
}
for (const child of node.children) {
count += getChildrenCount(child)
}
return count;
}
const getSortedNodesWithChildrenCountLabel = nodes => {
return nodes
.reduce(function f (output, node) {
if (node.children) {
node.label += ` (${getChildrenCount(node)})`
node.children = node.children
.reduce(f, [])
}
output.push(node)
return output
}, [])
}
console.log(getSortedNodesWithChildrenCountLabel(nodes))
我需要递归循环遍历 object 的数组,每个 object object 都有一个 属性 label
需要修改为包括 children
计数。
看看这个例子:
const nodes = [{
value: 'World',
label: 'World',
children: [{
label: 'Europe',
value: 'Europe',
children: [
{
label: 'Albania',
value: 'AL'
},
{
label: 'BeNeLux',
value: 'BeNeLux',
children: [
{
label: 'The Netherlands',
value: 'NL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Luxembourg',
value: 'LU'
}
]
}
]
}]
}]
预期输出为:
const expectedOutput = [{
value: 'World',
label: 'World (4)',
children: [{
label: 'Europe (4)',
value: 'Europe',
children: [
{
label: 'Albania',
value: 'AL'
},
{
label: 'BeNeLux (3)',
value: 'BeNeLux',
children: [
{
label: 'The Netherlands',
value: 'NL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Luxembourg',
value: 'LU'
}
]
}
]
}]
}]
这就是我现在所做的工作,但它无法正常工作,因为如上文 expectedOutput
所述,Europe
的标签将是 Europe (4)
而我的版本计数 Europe (2)
因为它忽略了欧洲内部的 children。
export const getSortedNodesWithChildrenCountLabel = nodes => {
return nodes
.reduce(function f (output, node) {
if (node?.children) {
node.label += ` (${node.children.length})`
node.children = node.children
.reduce(f, [])
}
output.push(node)
return output
}, [])
}
您可以采用递归方法并从子项中获取计数并更新 label
。
这种方法会改变数据。
function update(nodes) {
return nodes.reduce((count, node) => {
if (node.children) {
var subcount = update(node.children);
node.label += ` (${subcount})`;
return count + subcount;
}
return count + 1;
}, 0);
}
const nodes = [{ value: 'World', label: 'World', children: [{ label: 'Europe', value: 'Europe', children: [{ label: 'Albania', value: 'AL' }, { label: 'BeNeLux', value: 'BeNeLux', children: [{ label: 'The Netherlands', value: 'NL' }, { label: 'Belgium', value: 'BE' }, { label: 'Luxembourg', value: 'LU' }] }] }] }];
update(nodes);
console.log(nodes);
.as-console-wrapper { max-height: 100% !important; top: 0; }
一个非变异版本,它通过外部调用的对象获取计数。
function fn(count = { count: 0 }) {
return function ({ value, label, children }) {
var sub = { count: 0 };
if (children) {
children = children.map(fn(sub)),
label += ` (${sub.count})`;
count.count += sub.count;
return { value, label, children };
}
count.count++;
return { value, label };
};
}
const
nodes = [{ value: 'World', label: 'World', children: [{ label: 'Europe', value: 'Europe', children: [{ label: 'Albania', value: 'AL' }, { label: 'BeNeLux', value: 'BeNeLux', children: [{ label: 'The Netherlands', value: 'NL' }, { label: 'Belgium', value: 'BE' }, { label: 'Luxembourg', value: 'LU' }] }] }] }],
withCount = nodes.map(fn());
console.log(withCount);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以将儿童计数分解为单独的递归函数:
const nodes = [{
value: 'World',
label: 'World',
children: [{
label: 'Europe',
value: 'Europe',
children: [
{
label: 'Albania',
value: 'AL'
},
{
label: 'BeNeLux',
value: 'BeNeLux',
children: [
{
label: 'The Netherlands',
value: 'NL'
},
{
label: 'Belgium',
value: 'BE'
},
{
label: 'Luxembourg',
value: 'LU'
}
]
}
]
}]
}]
const getChildrenCount = (node, count = 0) => {
if (!node.children) {
return 1
}
for (const child of node.children) {
count += getChildrenCount(child)
}
return count;
}
const getSortedNodesWithChildrenCountLabel = nodes => {
return nodes
.reduce(function f (output, node) {
if (node.children) {
node.label += ` (${getChildrenCount(node)})`
node.children = node.children
.reduce(f, [])
}
output.push(node)
return output
}, [])
}
console.log(getSortedNodesWithChildrenCountLabel(nodes))