C#将非分层CSV数据放入层次结构中

时间:2018-04-20 07:48:50

标签: c# structure hierarchy

我们有一个第三方工作流程系统,其中包含以下列格式存储为平面文件的操作的分层列表:

  • 根节点1
  • 根节点1-节点1
  • 根节点1-节点2
  • 根节点1-节点2-Node1上
  • 根节点1-节点2-节点1-节点1
  • 根节点1-节点2-节点1-节点2
  • 根节点2
  • 根节点2-Node1上

等...

在每个节点下面是一个属性列表,这个项目的目的是编写一个小程序,它将遍历每个文件,从根节点关系构建层次结构,然后我们就可以使用这个模型来运行报告数据。

到目前为止,我的尝试是创建一个Node类,其中包含Child类型的List<Node>属性,它将存储层次结构

我正在努力弄清楚如何确定哪个节点应该是哪个节点的子节点。我当前的过程是捕获先前的节点名称,如果当前节点名称包含前一个节点名称,它必须是一个子节点,但我发现当它有几个节点深时,它就变成了flakey。

有没有人建议以更可靠的方式描述这些关系?

1 个答案:

答案 0 :(得分:1)

这样的事情应该有效:

public class Node
{
    public string Key { get; set; }
    public Node Parent { get; set; }
    public IList<Node> Children { get; set; }
}

private Node LoadAll(string[] keys)
{
    var nodes = new Dictionary<string, Node>(StringComparer.OrdinalIgnoreCase);
    var orphanNodes = new List<Node>();
    Node root = null;
    foreach (var key in keys)
    {
        var node = new Node()
        {
            Key = key
        };
        nodes[key] = node;

        int keySeparator = key.LastIndexOf("-");
        if (keySeparator != -1)
        {
            string parentKey = key.Substring(0, keySeparator);
            if (nodes.TryGetValue(parentKey, out var parentNode))
            {
                if (parentNode.Children == null)
                {
                    parentNode.Children = new List<Node>();
                }
                node.Parent = parentNode;
                parentNode.Children.Add(node);
            }
            else
            {
                orphanNodes.Add(node);
            }
        }
        else if (root != null)
        {
            throw new Exception("Root node already exists.");
        }
        else
        {
            root = node;
        }
    }
    foreach (var orphan in orphanNodes)
    {
        string parentKey = orphan.Key.Substring(0, orphan.Key.LastIndexOf("-"));
        if (nodes.TryGetValue(parentKey, out var parentNode))
        {
            if (parentNode.Children == null)
            {
                parentNode.Children = new List<Node>();
            }
            orphan.Parent = parentNode;
            parentNode.Children.Add(orphan);
        }
        else
        {
            throw new Exception("Nodes without parents found.");
        }
    }
    return root;
}

它维护所有节点(nodes)及其键的列表,以便可以轻松地从其键中查找任何节点。它还维护了一个节点列表,我们在初始循环中没有任何父节点(orphanNodes - 如果父节点总是在子节点之前,则可以删除它。)

对于每个键我们:

  1. 创建节点
  2. 的实例
  3. 提取父键
  4. 如果没有父键,则假设它是根元素
  5. 尝试找到父节点。如果找到,请将当前节点添加为子节点。如果找不到,请将当前节点添加为孤儿。
  6. 如果在子节点之后加载了任何父节点,我们将为每个孤儿执行以下操作:

    1. 提取父密钥。
    2. 尝试找到父节点。如果找到,请将当前节点添加为子节点。如果找不到,请抛出错误。
    3. 可能会改进某些字符串操作,但这是一种可以解决问题的方法。