Javascript-将嵌套对象转换为项目数组

时间:2018-08-26 17:02:26

标签: javascript javascript-objects hierarchy

我有一个看起来像这样的对象:

[
  {
    "id": 1,
    "name": "Electronics",
    "path": "Electronics",
    "children": [
      {
        "id": 2,
        "name": "Laptops & PC",
        "path": "Electronics > Laptops & PC",
        "children": []
      },
      {
        "id": 7,
        "name": "Phones & Accessories",
        "path": "Electronics > Phones & Accessories",
        "children": [
          {
            "id": 8,
            "name": "Smartphones",
            "path": "Electronics > Phones & Accessories > Smartphones",
            "children": [
              {
                "id": 9,
                "name": "Android",
                "path": "Electronics > Phones & Accessories > Smartphones > Android",
                "children": []
              },
              {
                "id": 10,
                "name": "iOS",
                "path": "Electronics > Phones & Accessories > Smartphones > iOS",
                "children": []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "id": 11,
    "name": "Software",
    "path": "Software",
    "children": []
  }
]

我想将其转换为如下形式:

[
  {header: 'Electronics'},
  {name: 'Laptops & PC', group: 'Electronics', id: 2},
  {name: 'Phones & Accessories', group: 'Electronics', id: 7},
  {name: 'Smartphones', group: 'Phones & Accessories', id: 8},
  {name: 'Android', group: 'Smartphones', id: 9},
  {name: 'iOS', group: 'Smartphones', id: 10},
  {divider: true},
  {name: 'Software', group: 'Software', id: 11}
]

基本上,

  • 如果根元素具有子元素,则应将其转换为header
  • 所有元素的父名称都应为group
  • 完成一个根元素后,需要插入{divider: true}才能进行下一个元素。 (如果这是最后一个根元素,请不要插入{divider: true}

虽然我能够在stackoverflow上找到许多从JSON到Hierarchical的解决方案,但我却无法对这些解决方案进行反向工程。

有人可以帮我吗?

2 个答案:

答案 0 :(得分:2)

您可以通过检查标头保留相应的分隔符并迭代子代来采取迭代和递归的方法。

然后,您需要为任何项目添加标准对象。

递归回调对组使用闭包。如果未设置,则该组为根项目。

public class TotalItemValue:IEntity
{
    public int Id { get; set; }

    public int? TotalItemCategoryId { get; set; }

    [StringLength(125)]
    public string Label { get; set; }

    public decimal? Value { get; set; }
    public int? Quantity { get; set; }
    public int QuoteId { get; set; }
    public int? TotalTemplateId { get; set; }

    public bool AllowDataEntry { get; set; }
    public bool IsMiscellaneous { get; set; }

    public TotalItemCategory TotalItemCategory { get; set; }
    public TotalTemplate TotalTemplate { get; set; }
}
public ActionResult CreateMiscellaneousItem(int quoteId)
{
    TotalItemValue totalItemValue = _expressionTotalService.CreateMiscellaneousItem(quoteId);
    return View(totalItemValue);
}

[HttpPost]
public ActionResult CreateMiscellaneousItem( TotalItemValue value)
{
    _expressionTotalService.SaveMiscellaneousItem(value);

    return RedirectToAction("Totals", new{quoteId=value.QuoteId});
}

答案 1 :(得分:1)

这是一种递归方法,使用array.reduce和散布运算符(...)在数据移动时将列表变平,并使用一个单独的辅助函数来处理非标题:

const flatten = data => 
  data.reduce((a, e, i) => {
    if (e.children.length) {
      a.push({header: e.name});
      a.push(...flattenR(e.children, e.name));
    }
    else {
      a.push({name: e.name, group: e.name, id: e.id});
    }
    
    if (i < data.length - 1) {
      a.push({divider: true});
    }
    
    return a;
  }, [])
;

const flattenR = (data, grp) => 
  data.reduce((a, e) => {
    a.push({name: e.name, group: grp, id: e.id});
    a.push(...flattenR(e.children, e.name));
    return a;
  }, [])
;

const data = [
  {
    "id": 1,
    "name": "Electronics",
    "path": "Electronics",
    "children": [
      {
        "id": 2,
        "name": "Laptops & PC",
        "path": "Electronics > Laptops & PC",
        "children": []
      },
      {
        "id": 7,
        "name": "Phones & Accessories",
        "path": "Electronics > Phones & Accessories",
        "children": [
          {
            "id": 8,
            "name": "Smartphones",
            "path": "Electronics > Phones & Accessories > Smartphones",
            "children": [
              {
                "id": 9,
                "name": "Android",
                "path": "Electronics > Phones & Accessories > Smartphones > Android",
                "children": []
              },
              {
                "id": 10,
                "name": "iOS",
                "path": "Electronics > Phones & Accessories > Smartphones > iOS",
                "children": []
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "id": 11,
    "name": "Software",
    "path": "Software",
    "children": []
  }
];

console.log(flatten(data));