2012-08-13 32 views
7

Tôi chắc chắn có một cách thực sự đơn giản để thực hiện điều này nhưng tôi không thể tìm ra. Tôi có một số dữ liệu đầu vào trông giống như sau:D3: sử dụng chức năng lồng để chuyển dữ liệu phẳng với khóa chính thành một hệ thống phân cấp

[ 
{id: 1, name: "Peter"}, 
{id: 2, name: "Paul", manager: 1}, 
{id: 3, name: "Mary", manager: 1}, 
{id: 4, name: "John", manager: 2}, 
{id: 5, name: "Jane", manager: 2} 
] 

Nếu có thể, tôi muốn sử dụng toán tử tổ d3.js để có cấu trúc sử dụng trong bố cục phân cấp. Như thế này:

[ 
    {name: "Peter", children: [ 
      {name:"Paul", children: [ 
       {name:"John"}, 
       {name:"Jane"} 
      ]}, 
      {name:"Mary"} 
     ] 
    } 
] 

Trả lời

12

Bạn không thể sử dụng toán tử lồng tại đây vì lồng tạo phân cấp cố định: số cấp trong phân cấp đầu ra giống với số lượng hàm chính bạn chỉ định.

Điều đó nói rằng, bạn có thể viết chức năng của riêng bạn tạo ra một cây. Giả sử rằng nút gốc là nút đầu tiên trong mảng đầu vào, bạn có thể tạo một bản đồ từ id đến nút, và sau đó xây dựng cây một cách lười biếng.

function tree(nodes) { 
    var nodeById = {}; 

    // Index the nodes by id, in case they come out of order. 
    nodes.forEach(function(d) { 
    nodeById[d.id] = d; 
    }); 

    // Lazily compute children. 
    nodes.forEach(function(d) { 
    if ("manager" in d) { 
     var manager = nodeById[d.manager]; 
     if (manager.children) manager.children.push(d); 
     else manager.children = [d]; 
    } 
    }); 

    return nodes[0]; 
} 

Nếu bạn biết rằng các nút được liệt kê theo thứ tự sao cho người quản lý xuất hiện trước báo cáo của họ, bạn có thể đơn giản hóa mã để chỉ lặp lại một lần.

+1

Cảm ơn rất nhiều, điều này rất hữu ích. Tôi thực sự đã kết thúc bắt đầu từ phía trên cùng của cây bằng cách (1) tạo tra cứu dựa trên người quản lý (từ điển của mảng), (2) bắt đầu với một gốc đã biết, thêm các đệ quy cho mỗi báo cáo. – prauchfuss

Các vấn đề liên quan