2013-04-09 55 views
7

Tôi có điều này cấu trúc dữ liệu JSON:D3 JSON chuyển đổi dữ liệu

[ 
    { "dep": "d1", "name": "name1", "size": "size1" }, 
    { "dep": "d1", "name": "name2", "size": "size2" }, 
    { "dep": "d2", "name": "name1", "size": "size3" }, 
    { "dep": "d2", "name": "name1", "size": "size4" } 
] 

và tôi muốn chuyển nó sang một cấu trúc lồng nhau như thế này:

{ 
    "name": "root", 
    "children": [ 
     { "name": "d1", 
      "children": [ 
       { "dep": "d1", "name": "name1", "size": "size1" }, 
       { "dep": "d1", "name": "name2", "size": "size2" } 
      ] 
     }, 
     { "name": "d2", 
      "children": [ 
       { "dep": "d2", "name": "name1", "size": "size3" }, 
       { "dep": "d2", "name": "name2", "size": "size4" } 
      ] 
     } 
    ] 
} 

... và tiếp tục sử dụng nó để làm cho số Reingold–Tilford Tree. Bất cứ ai có thể chỉ cho tôi đúng hướng, tôi khá mới với D3!

+0

FYI, trong khi bạn có thể nhận dữ liệu dưới dạng JSON khi bạn chuyển đổi nó, bạn đang làm việc với các đối tượng và mảng JavaScript. Tại thời điểm này, vấn đề không liên quan gì đến JSON nữa. –

+0

http://stackoverflow.com/questions/17847131/generate-multilevel-flare-json-data-format-from-flat-json Điều này sẽ giải quyết được mục đích của bạn. –

+0

Bạn đã tạo cấu trúc dữ liệu Json ban đầu như thế nào? Bạn đã có nguồn dữ liệu và được thêm vào dữ liệu chưa? Hay chỉ là mã cứng? –

Trả lời

9

Chiến lược là tạo cấu trúc dữ liệu trống mới tương ứng với những gì bạn muốn và sau đó điền vào nó bằng cách trải qua toàn bộ tập dữ liệu gốc. Đây là mã:

var data = [ 
    { "dep": "d1", "name": "name1", "size": "size1" }, 
    { "dep": "d1", "name": "name2", "size": "size2" }, 
    { "dep": "d2", "name": "name1", "size": "size3" }, 
    { "dep": "d2", "name": "name2", "size": "size4" } 
] 

var newData = {"name": "root", "children": {}} 

data.forEach(function (d) { 
    if (typeof newData.children[d.dep] !== 'undefined') { 
     newData.children[d.dep].children.push(d) 
    } else { 
     newData.children[d.dep] = {"name": d.dep, "children": [d]} 
    } 
}) 
newData.children = Object.keys(newData.children).map(function (key) { 
    return newData.children[key]; 
}); 

Bài tập cuối cùng là chuyển đối tượng thành mảng.

Mà cho kết quả mong muốn cho newData:

{ 
    "name": "root", 
    "children": [ 
     { "name": "d1", 
      "children": [ 
       { "dep": "d1", "name": "name1", "size": "size1" }, 
       { "dep": "d1", "name": "name2", "size": "size2" } 
      ] 
     }, 
     { "name": "d2", 
      "children": [ 
       { "dep": "d2", "name": "name1", "size": "size3" }, 
       { "dep": "d2", "name": "name2", "size": "size4" } 
      ] 
     } 
    ] 
} 

jsFiddle:http://jsfiddle.net/chrisJamesC/eB4jF/

Lưu ý: Phương pháp này không làm việc cho các cấu trúc lồng nhau. Nó sẽ là cách khó hơn để làm điều này cho các cấu trúc lồng nhau nhưng bạn luôn có thể sử dụng một hàm đệ quy.


EDIT: Theo đề nghị của @imarane trong câu trả lời của mình, bạn có thể sử dụng d3.nest() đó là cách tốt hơn so với bàn tay của tôi đã giải quyết. Do đó bạn có thể chấp nhận câu trả lời của mình. Bằng cách chơi với nó, thậm chí nó là rất dễ dàng để có nhiều cấp độ của tổ:

var data = [ 
    { "dep": "d1", "name": "name1", "size": "size1" }, 
    { "dep": "d1", "name": "name2", "size": "size2" }, 
    { "dep": "d2", "name": "name1"}, 
    { "dep": "d2"} 
] 

var newData = { 
    "key":"root", 
    "children": 
     d3.nest() 
      .key(function(d){return d.dep}) 
      .key(function(d){return d.name}) 
      .key(function(d){return d.size}) 
      .entries(data) 
}  

nào cho:

{"key":"root","children":[ 
    {"key":"d1","values":[ 
     {"key":"name2","values":[ 
      {"dep":"d1","name":"name2","size":"size1"}, 
      {"dep":"d1","name":"name2","size":"size2"} 
     ]} 
    ]}, 
    {"key":"d2","values":[ 
     {"key":"name1","values":[ 
      {"dep":"d2","name":"name1"} 
     ]}, 
     {"key":"undefined","values":[ 
      {"dep":"d2"} 
     ]} 
    ]} 
]} 

Những cấu trúc dữ liệu sau (Tôi hy vọng tốt hơn để hiểu toàn bộ điểm):

var data = [ 
    { "dep": "d1", "name": "name2", "size": "size1" }, 
    { "dep": "d1", "name": "name2", "size": "size2" }, 
    { "dep": "d2", "name": "name1"}, 
    { "dep": "d2"} 
] 

JsFiddle:http://jsfiddle.net/chrisJamesC/eB4jF/2/

Thông tin thêm về Nest:http://bl.ocks.org/phoebebright/raw/3176159/

+0

Cảm ơn, tôi sẽ cung cấp cho bạn lựa chọn đầu tiên một thử ... Tôi đã chơi với .nest() và nó làm việc để chuyển đổi dữ liệu. Nhưng "bố cục cây" muốn "tên": và "con" làm mặc định và tôi không thể lấy "khóa": và "giá trị": để hoạt động. – alta

+0

... tùy chọn đầu tiên hoạt động như một sự quyến rũ! Phần d3.nest() rất hiệu quả nhưng các "giá trị" và "giá trị" cần được làm việc xung quanh. Cảm ơn! – alta

+1

Bạn có bất cứ đề nghị nào: Cách ánh xạ tất cả "khóa" thành "tên" và "giá trị" cho "trẻ em" trong lần 2 của bạn. gợi ý? – alta

4

tùy chọn khác là sử dụng phương pháp tổ xây dựng vào D3 ....

var nested = d3.nest() 
.key(function(d,i){ return d.dep; }) 
.entries(data); 

mà kết quả đầu ra:

[ 
    { 
    "key": "d1", 
    "values": [ 
     { 
     "dep": "d1", 
     "name": "name1", 
     "size": "size1" 
     }, 
     { 
     "dep": "d1", 
     "name": "name2", 
     "size": "size2" 
     } 
    ] 
    }, 
    { 
    "key": "d2", 
    "values": [ 
     { 
     "dep": "d2", 
     "name": "name1", 
     "size": "size3" 
     }, 
     { 
     "dep": "d2", 
     "name": "name2", 
     "size": "size4" 
     } 
    ] 
    } 
] 

JsFiddle: http://jsfiddle.net/imrane/bSGrG/1/

+0

Cảm ơn, tôi đã thử cái này. Nhưng như tôi đã đề cập, tôi không thể có được ánh xạ "chìa khóa" và "giá trị" để "tên": và "trẻ em": vì nó được yêu cầu bởi bố cục cây. Tôi chắc rằng bạn có một số thủ thuật trong tay áo của bạn để lập bản đồ? – alta

+0

well - trong ví dụ cây bạn có thể thay đổi accessor con thành d.values ​​bằng cách sử dụng d3.layout.tree(). Children (function (d) {return d.values}) ... xem ở đây cho những gì chúng đã làm .. http://blog.pixelingene.com/2011/07/building-a-tree-diagram-in-d3-js/ – imrane

+0

tại đây https://groups.google.com/forum/?fromgroups=#!topic/d3-js/L3UeeUnNHO8 và ở đây http://stackoverflow.com/questions/11088303/how-to-convert-to-d3s-json-format ... đây là những cái cũ nên tôi không biết những gì đã thay đổi kể từ đó. GL. – imrane

0

Xin chào các bạn, tôi nghĩ tôi đã tìm thấy một giải pháp khá đơn giản. Tôi đã hoàn thành một tổ hợp rất đẹp của một tập dữ liệu lớn (400.000 hàng) cho một biểu đồ thanh phân cấp theo cách rất hợp lý. Nó sử dụng thư viện Underscore và một hàm bổ sung _.nest.Chỉ cần tải xuống và bao gồm hai thư viện cần thiết

src="underscore-min.js" 
src="underscore.nest.js" 

Sau đó, sử dụng chức năng _.nest để tạo cấu trúc của bạn. Dưới đây là dòng của tôi:

var newdata = _.nest(data, ["Material", "StudyName"]); 

"Material""StudyName" là cột tôi muốn nhóm cấu trúc của tôi để.

Có các tùy chọn khác để sử dụng chức năng này nếu bạn cần thực hiện nhiều việc hơn nhưng tôi sẽ để nó như thế này

0

Sử dụng tính năng này. U có thể kiểm tra đầu ra trong giao diện điều khiển của trình duyệt nếu bạn cần.

function reSortRoot(root, value_key) { 
       //console.log("Calling"); 
       for (var key in root) { 
        if (key == "key") { 
         root.name = root.key; 
         delete root.key; 
        } 
        if (key == "values") { 
         root.children = []; 
         for (item in root.values) { 
          root.children.push(reSortRoot(root.values[item], 
            value_key)); 
         } 
         delete root.values; 
        } 
        if (key == value_key) { 
         root.value = parseFloat("1"); 
         delete root[value_key]; 
        } 
       } 
       return root; 
      } 

      var testdata=[ 
          { "dep": "d1", "name": "name1", "size": "size1" }, 
          { "dep": "d1", "name": "name2", "size": "size2" }, 
          { "dep": "d2", "name": "name1", "size": "size3" }, 
          { "dep": "d2", "name": "name1", "size": "size4" } 
         ]; 

      var testJson = d3.nest() 
      .key(function(d) { return d.dep; }) 
      .entries(testdata); 
      console.log(testJson); 

      var testRoot={}; 
      testRoot.key = "Information"; 
      testRoot.values = testJson; 
      testRoot = reSortRoot(testRoot, "name"); 

      console.log(testRoot); 
Các vấn đề liên quan