0

Fiddle Example

I want to convert this JSON data

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"
  }
];

into a hierarchical form for a d3 graph:

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

I came up with this code to generate the format:

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

Is it possible , during the iteration, not to push a country into the brand or computer's children array if the country's children array is empty?

For example, these objects should be removed

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

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

Here's the part that push each country into each category's children array:

    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":[]});
     }
    }

My approach is probably wrong, so any other suggestions converting the data into that hierarchical form is also appreciated.

2 Answers 2

2

Check this fiddle, is this what you're looking for? I decided to go for a different approach to the one you followed, hope you don't mind. I've commented the code so that it's clearer:

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

Hope it helps.

Sign up to request clarification or add additional context in comments.

Comments

0

You have to use d3.nest() function to group array elements hierarchically. The documentation is available here. Also go through this tutorial which could definitely help you to create hierarchical data.

That's not enough, you get hierarchical data in terms of key and value pairs. But if you want to convert into name and children, already a question on SO is asked, check this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.