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

Javascript - Convert Nested Object to Array of items

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

[
  {
    "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}
]

基本上,

虽然我能够在 Whosebug 上找到很多从层次结构到 JSON 的解决方案,但我无法对这些解决方案进行逆向工程。

有人可以帮我吗?

您可以通过检查 header 保持相应的分隔符并迭代 children.

来采用迭代和递归方法

然后您需要为任何项目添加标准 object。

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

function getParts(array) {
    var result = [];
    array.forEach(function iter(group) {
        return function ({ id, name, children }, i, { length }) {
            if (!group && children.length) {
                result.push({ header: name });
            }
            if (group || !children.length) {
                result.push({ name, group: group || name, id });
            }
            children.forEach(iter(name));
            if (!group && i + 1 !== length) {
                result.push({ divider: true });
            }
        };
    }(''));
    return result;
}

var 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: [] }, { id: 11, name: "Software", path: "Software", children: [] }, { id: 11, name: "Software", path: "Software", children: [] }],
    result = getParts(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

这是一种递归方法,使用 array.reduce 和扩展运算符 (...) 在您移动数据时展平列表,还有一个单独的辅助函数来处理 non-headers :

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