对象的递归数组以追加属性子项计数

时间:2019-08-04 16:46:35

标签: javascript recursion mapreduce

我需要递归遍历对象数组,并且每个对象对象都有一个属性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),而我的版本数为{{1 }},因为它无视欧洲内部的孩子。

Europe (2)

2 个答案:

答案 0 :(得分:1)

您可以采用递归方法,从子级获取计数并更新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; }

答案 1 :(得分:1)

您可以将子级分解为单独的递归函数:

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))