如何将分层csv(分号分隔)转换为多维数组

时间:2016-05-02 22:43:59

标签: javascript arrays csv d3.js multidimensional-array

我在csv中有分层数据:不同的级别用分号分隔,值用逗号分隔(在"行"的末尾):

Parent1;Child1;Grandchild1;3;3,5
Parent1;Child1;Grandchild2;3;3,5
Parent2;Child2;Grandchild2;4,4
Parent3;Child4;Grandchild1;5,5

我希望使用javascript / jQuery / d3.js将其转换为多维数组,如下所示:

var tree = [
  {
    text: "Parent 1",
    nodes: [
      {
        text: "Child 1",
        nodes: [
          {
            text: "Grandchild 1"
          },
          {
            text: "Grandchild 2"
          }
        ]
      },
      {
        text: "Child 2"
      }
    ]
  },
  {
    text: "Parent 2"
  },
  {
    text: "Parent 3"
  },
  {
    text: "Parent 4"
  },
  {
    text: "Parent 5"
  }
];

困难似乎是我需要递归循环并小心数组的深度(我不希望该值成为我的多维数组的一部分)。

目前我的代码看起来像这样,但它无法正常工作:

function createNavi(jsonRoot){

function printParentAddChildren(parent){

    var parentObj = {};
    parentObj.text = parent.name; 
    parentObj.backColor = colors[parent.depth];

    var children = parent.children;//array of objects(children)
    if(children==null)return parentObj;

    parentObj.node = [];

    for(var i=0;i<children.length;i++){
        parentObj.node.push(printParentAddChildren(children[i]));    
    }
    return parentObj; 
}

    var tree = [];
    var children = jsonRoot.children; //array of objects(children)
    for(var i=0;i<children.length;i++){
        tree.push(printParentAddChildren(children[i]));    
    }
    $('#tree').treeview({
          data: tree
    });
    console.log(tree);   
};

我想对你们这些人来说很容易! 提前感谢您的努力!

2 个答案:

答案 0 :(得分:2)

这正是d3.nest的意思。

给定文件 test.csv ,如:

p;c;g;r1;r2
Parent1;Child1;Grandchild1;3;3,5
Parent1;Child1;Grandchild2;3;3,5
Parent2;Child2;Grandchild2;4,4
Parent3;Child4;Grandchild1;5,5

此:

var dsv = d3.dsv(";", "text/plain");
  dsv("test.csv", function(data){
    var n = d3.nest()
      .key(function(d){ return d.p })
      .key(function(d){ return d.c })
      .key(function(d){ return d.g })
      .entries(data);
  });

生成n为:

[{
  "key": "Parent1",
  "values": [{
    "key": "Child1",
    "values": [{
      "key": "Grandchild1",
      "values": [{
        "p": "Parent1",
        "c": "Child1",
        "g": "Grandchild1",
        "r1": "3",
        "r2": "3,5"
      }]
    }, {
      "key": "Grandchild2",
      "values": [{
        "p": "Parent1",
        "c": "Child1",
        "g": "Grandchild2",
        "r1": "3",
        "r2": "3,5"
      }]
    }]
  }]
}, {
  "key": "Parent2",
  "values": [{
    "key": "Child2",
    "values": [{
      "key": "Grandchild2",
      "values": [{
        "p": "Parent2",
        "c": "Child2",
        "g": "Grandchild2",
        "r1": "4,4"
      }]
    }]
  }]
}, {
  "key": "Parent3",
  "values": [{
    "key": "Child4",
    "values": [{
      "key": "Grandchild1",
      "values": [{
        "p": "Parent3",
        "c": "Child4",
        "g": "Grandchild1",
        "r1": "5,5"
      }]
    }]
  }]
}]

工作代码here

评论的编辑

  var dsv = d3.dsv(";", "text/plain");
  dsv("test.csv", function(data){
    var n = d3.nest()
      .key(function(d){ return d.p })
      .key(function(d){ return d.c })
      .rollup(function(d){
        return d.map(function(d1){
          return {key: d1.g};
        })
      })
      .entries(data);

    function renameKeys(obj){
      obj.forEach(function(d){
        d.text = d.key;
        delete d.key;
        if (d.values){
          d.nodes = d.values;
          delete d.values;
          renameKeys(d.nodes);
        }
      });
    }

    renameKeys(n);

  });

产地:

[{
  "text": "Parent1",
  "nodes": [{
    "text": "Child1",
    "nodes": [{
      "text": "Grandchild1"
    }, {
      "text": "Grandchild2"
    }]
  }]
}, {
  "text": "Parent2",
  "nodes": [{
    "text": "Child2",
    "nodes": [{
      "text": "Grandchild2"
    }]
  }]
}, {
  "text": "Parent3",
  "nodes": [{
    "text": "Child4",
    "nodes": [{
      "text": "Grandchild1"
    }]
  }]
}]

更新了code

答案 1 :(得分:0)

嗯,我想这就像纯JS一样。如你所见,它不是很多代码,而是一个复杂的代码。让我先展示代码,然后我将介绍它。

&#13;
&#13;
var csv = "Parent1;Child1;Grandchild1;3;3,5\nParent1;Child1;Grandchild2;3;3,5\nParent2;Child2;Grandchild2;4,4\nParent3;Child4;Grandchild1;5,5";

function construct(csv){
  var arr = csv.split("\n").map(e => e.match(/[A-Za-z]+\d*/g));
  function nest(a,p){
    var fi = p.findIndex(e => e.text == a[0]);
    ~fi ? "nodes" in p[fi] ? nest(a.slice(1),p[fi].nodes)
                           : a.length > 1 && (p[fi].nodes = nest(a.slice(1),[]))
        : (p.push({"text": a[0]}),
           nest(a,p));
    return p;
  }
  return arr.reduce((p,c) => {p = nest(c,p); return p},[]);
}

document.write("<pre>" + JSON.stringify(construct(csv), null, 2) + "</pre>")
&#13;
&#13;
&#13;

确定construct函数接受csv文本,首先将事物转换为数组数组,将每行中的每个单词保存为

等项
[ [ 'Parent1', 'Child1', 'Grandchild1' ],
  [ 'Parent1', 'Child1', 'Grandchild2' ],
  [ 'Parent2', 'Child2', 'Grandchild2' ],
  [ 'Parent3', 'Child4', 'Grandchild1' ] ]

construct函数负责构造具有父对象作为项的最外层数组。它通过使用具有空数组初始值的Array.prototype.reduce()实现来完成这项工作。 nest函数递归地处理内部数组元素,它就是所有blackmagic发生的地方。