【问题标题】:Converting csv file data to a JavaScript dictionary将 csv 文件数据转换为 JavaScript 字典
【发布时间】:2020-11-21 19:37:00
【问题描述】:

CSV 文件数据:

parent_name, child_name
A1, A2
A1, A3
A1, A4
A1, A5
A2, A12
A2, A16
A2, A18
A2, A19

输出:要制作的 Javascript 对象

{
name: A1,
children: [
            {
             name: A2,
             children: [
                        {
                         name: A4,
                         children: []
                        }
                       ]
            },
            {
             name: A3,
             children: []
            }
}

基本上,我必须转换 CSV 文件才能在 d3 中创建树。 我想知道如何制作 CSV 文件所需的字典

d3.csv("test1.csv").then(function (data) {
        var dataset = {};
        data.forEach(function (d,i){
            console.log(d.parent_name, d.child_name);
            if(i === 0){
                dataset["name"]  = d.parent_name;
                dataset["children"] = [];
            }
            if (dataset["name"] === d.parent_name){
                dataset.children.push(NodeMaker(d.child_name))
            }
        });
        function NodeMaker(name){
            return {"name": name, "children": []};
        }
        console.log(dataset);
    });

所以这是我的代码,它只制作一个类似字典的代码, 它不会比根节点的第一级更深

{
name: A1,
children: [
           {
             name: A2,
             children: []
           },
           {
             name: A3,
             children: []
           }
           ]
}

【问题讨论】:

  • 你能告诉我'A3'要去哪里吗?
  • 您的示例输出似乎错误,因为输出中没有 A3 的迹象。
  • 请加你试试。出了什么问题?
  • 更新了@NinaScholz 出了什么问题
  • 为什么不使用d3.stratify()。这正是它的目的所在。

标签: javascript csv d3.js


【解决方案1】:

目前您只检查节点是否与根(第一个)节点匹配。一种想法可能是遍历现有树并检查要添加的父节点是否已经存在,然后向其添加子节点。但这有一些问题:它需要回溯数据,因此效率低下;如果您遇到还不是树的一部分的parent_node,会发生什么?正如 vicatcu 指出的那样,一种更有效(和健壮)的方法是在遇到节点时创建节点并将它们保存在字典/查找对象中。

它可能看起来像这样:

var sampleData = [
    { parent_name: 'A1', child_name: 'A2' },
    { parent_name: 'A1', child_name: 'A3' },
    { parent_name: 'A1', child_name: 'A4' },
    { parent_name: 'A1', child_name: 'A5' },
    { parent_name: 'A2', child_name: 'A12' },
    { parent_name: 'A2', child_name: 'A16' },
    { parent_name: 'A2', child_name: 'A18' },
    { parent_name: 'A2', child_name: 'A19' }
]

// if loading from a file, use this line instead to load data
// d3.csv("test1.csv").then(function (data) {
Promise.resolve(sampleData).then(function (data) {
    var lookup = {};
    data.forEach(function (d,i) {
        var parentNode = getNode(d.parent_name);
        parentNode.children.push(getNode(d.child_name));
    });
    function getNode(name) {
        if (!lookup[name]) {
            // if the node doesn't exist, make it
            lookup[name] = NodeMaker(name);
        }
        return lookup[name];
    }
    function NodeMaker(name){
        return {"name": name, "children": []};
    }
    // if the first parent node is the root, it represents the whole tree
    var tree = lookup[data[0].parent_name];
    console.log(tree);
    // do something with `tree`
});

【讨论】:

  • 我已经更新了程序中的数据,似乎不适用于这些数据,@NinaScholz 代码也适用于数组数组,但每当我们从 d3 中的 CSV 文件读取数据时是一个像你这样的字典数组
  • @Swaraj,我不确定你的意思。你期望输出是什么?我已使用您问题中的数据更新了我的代码
【解决方案2】:

您可以使用一个对象来保持所有关系并添加未知节点作为根节点。

const
    data = [['A1', 'A2'], ['A1', 'A3'], ['A2', 'A4']],
    tree = function (data) {
        const t = { root: { children: [] } };
        data.forEach(([parent, name]) => {
            t[name] = t[name] || { name, children: [] };
            if (!t[parent]) t.root.children.push(t[parent] = { name: parent, children: [] });
            t[parent].children.push(t[name]);
         
        });
        return t.root.children;
    }(data);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 当您在 d3 中读取 CSV 文件时,它是字典数组的形式,而不是数组数组的形式,我尝试转换它,但它不起作用
  • 我已经更新了输入数据集。另外,您能否解决上述评论@NinaScholz
【解决方案3】:

首先使用一些库来解析它(我通常使用 csv-parse)。 接下来,遍历结果数组并通过将每条记录添加到树中逐步构建最终数据结构,这当然涉及为每一行确定树应如何更改(添加子节点或添加兄弟节点或其他) .我建议的一种效率是为树中的对象设置名称字典,以避免搜索它们,例如 {id: noderef} 以便您可以在恒定时间内找出父对象是否存在以及树中的位置。供您参考,您使用的 csv 格式在文献中有时称为邻接矩阵。

【讨论】:

  • 我已经上传了我的代码,你能指导我哪里出错了吗? @vicatcu
  • 嘿@vicatcu 你能详细说明一下吗
猜你喜欢
  • 2017-03-27
  • 2016-01-28
  • 1970-01-01
  • 2021-12-22
  • 2017-09-13
  • 2014-03-01
  • 2020-12-24
  • 2019-02-01
  • 1970-01-01
相关资源
最近更新 更多