【问题标题】:Build JSON from JavaScript array recursively从 JavaScript 数组递归构建 JSON
【发布时间】:2020-01-19 14:21:01
【问题描述】:

我想从 http 请求返回的数组中构建一个 JSON 对象 我的实际数组看起来像:

[{
    Description: "Product"
    IsInstanciable: false
    IsMasked: false
    Name: "ProductBase"
    Subclasses: [{
      Description: "Product2"
      IsInstanciable: false
      IsMasked: false
      Name: "ProductBase2",
      Count: 5,
      Subclasses:[]
    },
    {
      Description: "Product3"
      IsInstanciable: false
      IsMasked: false
      Name: "ProductBase3",
      Count: 4,
      Subclasses:[],
    }]
},
{
    Description: "Product4"
    IsInstanciable: false
    IsMasked: false
    Name: "ProductBase4",
    Count: '...',
    Subclasses: [...]
}

我想从上面的数组递归地创建一个 JSON 对象。它看起来像这样:

[
  {
    name: 'Product',
    Count: 9,
    children: [
      {name: 'Product2'},
      {name: 'Product3'},
    ]
  }, {
    name: 'Product4',
    children: [
      {
        name: '...',
        Count: 'Sum of Count in all children by level'
        children: [
          {name: '...'},
          {name: '...'},
        ]
      }
    ]
  },
];

这是我在打字稿中的递归函数,但它没有按预期工作。我该如何解决这个问题?

recursive(data, stack: TreeNode[]) {
    let elt: TreeNode = {name:'', children: []}
    if(data.Subclasses.length > 0) {
      elt.name = data.Description;
      data.Subclasses.forEach(element => {
        elt.children.push({name: element.Description});
        this.recursive(element, stack);
      });
    }else {
      elt.name = data.Description;
    }
    stack.push(elt);
  }

【问题讨论】:

    标签: javascript arrays typescript recursion


    【解决方案1】:

    我会将其分解为几个具有明确职责的独立功能:

    const sum = (ns) => 
      ns .reduce ((a, b) => a + Number (b), 0)
    
    const getCount = (product) => 
      (product .Count || 0) + sum ((product .Subclasses || []) .map (getCount))
    
    const extract = (product) => 
      ({
        name: product .Name,
        count: getCount (product),
        children: product .Subclasses .map (extract)
      })
    
    const extractAll = (products) => 
      products .map (extract)
    
    const products = [{"Description": "Product", "IsInstanciable": false, "IsMasked": false, "Name": "ProductBase", "Subclasses": [{"Count": 5, "Description": "Product2", "IsInstanciable": false, "IsMasked": false, "Name": "ProductBase2", "Subclasses": []}, {"Count": 4, "Description": "Product3", "IsInstanciable": false, "IsMasked": false, "Name": "ProductBase3", "Subclasses": []}]}, {"Count": 3, "Description": "Product4", "IsInstanciable": false, "IsMasked": false, "Name": "ProductBase4", "Subclasses": []}]
    
    console .log (
      extractAll (products)
    )

    (请注意,我更改了输出count 属性的大小写。它似乎与namechildren 更加一致。)

    我们通过对象递归得到它的Count属性,我们分别递归得到对象的其余部分。虽然可能有一种方法可以将这些结合起来,但我希望代码会更加复杂。

    请注意,我假设所有 Count 属性实际上都是数字,尽管您上面的示例包含一个字符串。如果您确实有像"3" 这样的值,那么getCount 需要更复杂一些。

    【讨论】:

      【解决方案2】:

      您可以将 map 函数与递归函数一起使用,如下所示:

      function MapObject(object) {
        if(!object || object.length < 0) return [];
      
        return object.map(obj => { return {
            name: obj.Description,
            children: MapObject(obj.Subclasses)
        }});
      }
      

      遵循完整的工作示例:

      var example = [{
          Description: "Product",
          IsInstanciable: false,
          IsMasked: false,
          Name: "ProductBase",
          Subclasses: [{
            Description: "Product2",
            IsInstanciable: false,
            IsMasked: false,
            Name: "ProductBase2",
            Subclasses:[]
          },
          {
            Description: "Product3",
            IsInstanciable: false,
            IsMasked: false,
            Name: "ProductBase3",
            Subclasses:[]
          }]
      },
      {
          Description: "Product4",
          IsInstanciable: false,
          IsMasked: false,
          Name: "ProductBase4"
      }]
      
      function MapObject(object) {
        if(!object || object.length < 0) return [];
        
        return object.map(obj => { return {
            name: obj.Description,
            children: MapObject(obj.Subclasses)
        }});
      }
      
      console.log(MapObject(example));

      【讨论】:

      • 嗨,Ricardo,如果我想按级别添加所有计数属性的总和怎么办?谢谢
      • 你能举个json的例子吗?
      • 我修改了上面问题中的json例子
      猜你喜欢
      • 2012-12-14
      • 1970-01-01
      • 2011-10-26
      • 2011-11-25
      • 2014-07-17
      • 2015-04-11
      • 2023-01-28
      • 2019-04-14
      • 1970-01-01
      相关资源
      最近更新 更多