转换为 javascript 中的分层数组

Converting into a hierarchical array in javascript

Fiddle Example

我想转换这个JSON数据

var data = [
  {
    "computer": 24,
    "brand": "Italy A",
    "phone": 0,
    "country": "Italy"
  },
  {
    "brand": "Italy C",
    "computer": 0,
    "phone": 0,
    "country": "Italy"
  },
  {
    "brand": "Brazil B",
    "computer": 0,
    "phone": 22,
    "country": "Brazil"
  },
  {
    "computer": 0,
    "brand": "Brazil D",
    "phone": 62,
    "country": "Brazil"
  },
  {
    "computer": 34,
    "brand": "US E",
    "phone": 41,
    "country": "US"
  }
];

转换为 d3 图的分层形式:

{
  "name": "categories",
  "children": [
    {
      "name": "phone",
      "children": [
        {
          "name": "US",
          "children": [
            {
              "brand": "US E",
              "size": 41
            }
          ]
        },
        {
          "name": "Brazil",
          "children": [
            {
              "brand": "Brazil B",
              "size": 22
            },
            {
              "brand": "Brazil D",
              "size": 62
            }
          ]
        },
        {
          "name": "Italy",
          "children": []
        }
      ]
    },
    {
      "name": "computer",
      "children": [
        {
          "name": "US",
          "children": [
            {
              "brand": "US E",
              "size": 34
            }
          ]
        },
        {
          "name": "Brazil",
          "children": []
        },
        {
          "name": "Italy",
          "children": [
            {
              "brand": "Italy A",
              "size": 24
            }
          ]
        }
      ]
    }
  ]
}

我想出了这段代码来生成格式:

function group_children(data){
    var categories = ["phone","computer"];
    var countries = ["US","Brazil","Italy"];
    var object = {name:"categories",children:[]};
    for(var c =0; c < categories.length;c++){
      object.children.push({"name":categories[c],children:[]});

     for(var con = 0;con < countries.length;con++){
       object.children[c].children.push({"name":countries[con],"children":[]});
     }
    }

    for(var i = 0;i < data.length;i++){
     var row = data[i];
     for(var c =0; c < categories.length;c++){
      for(var con = 0;con < countries.length;con++){
        var cat_key = categories[c],
            country_key = countries[con];
        if(row[cat_key] > 0){
          if(object.children[c].name == cat_key && row.country == country_key){  object.children[c].children[con].children.push({brand:row["brand"],size:row[cat_key]});        
          }
        }
      }   
    }
 }
 return object;
}

在迭代过程中,如果国家的 children 数组为空,是否可以不将国家推入品牌或计算机的 children 数组?

例如,应该删除这些对象

        // computer
        {
          "name": "Brazil",
          "children": []
        }
        // phone:

        {
          "name": "Italy",
          "children": []
        }

这是将每个国家推入每个类别的子数组的部分:

    for(var c =0; c < categories.length;c++){
      object.children.push({"name":categories[c],children:[]});

     for(var con = 0;con < countries.length;con++){
       object.children[c].children.push({"name":countries[con],"children":[]});
     }
    }

我的方法可能是错误的,因此也欢迎任何其他将数据转换为该层次结构形式的建议。

您必须使用 d3.nest() 函数对数组元素进行分层分组。文档可用 here. Also go through this 绝对可以帮助您创建分层数据的教程。

这还不够,您将根据键值对获得分层数据。但是如果你想转换成 name 和 children,已经有一个关于 SO 的问题,检查 this.

使用您当前的方法,您应该在推送国家/地区之前迭代数据以找到空数据,这将导致更多的迭代,而不是仅仅在最后迭代结果以过滤空数据。

否则,您应该在数据插入的相同迭代中创建结构,从而将迭代减少到 1。

检查此 fiddle,这是您要找的吗?我决定对你所遵循的方法采取不同的方法,希望你不介意。我已经对代码进行了注释,以使其更清晰:

var result = {
    name: "categories",
    children: [{
        "name": "phone",
            "children": []
    }, {
        "name": "computer",
            "children": []
    }]
};

$.each(data, function (index, item) {// Go through data and populate the result object.
    if (+item.computer > 0) { // Computer has items.
        filterAndAdd(item, result.children[1], "computer");
    }
    if (+item.phone > 0) { // Phone has items.
        filterAndAdd(item, result.children[0], "phone");
    }
});

function filterAndAdd(item, result_place, type) {// Search and populate.
    var i = -1;
    $.each(result_place.children, function (index,a) {
        if( a.name === item.country ) {
            i = index;
            return false;
        }
    });

    if (i > -1) {// Country already exists, add to children array.
        result_place.children[i].children.push({
            "brand": item.brand,
                "size": item[type]
        });
    } else {// Country doesn't exist, create it.
        result_place.children.push({
            "name": item.country,
                "children": [{
                "brand": item.brand,
                    "size": item[type]
            }]
        });
    }
}

希望对您有所帮助。