将一维项目列表排序到子/父结构中

时间:2013-12-26 15:36:59

标签: c#

我想知道某人是否能够提供帮助。

我有一个带有行的文本文件,我在\ t上拆分了。它们有两列,一个代码和一个名称。

我希望将这个一维结构拆分为代码列上的父子层次结构。

数据示例:

 0100000000     Coffee
 0110000000     Mocha
 0120000000     Cappuccino
 0121000000     Semi skimmed
 0121100000     Starbuckz
 0121200000     Costa
 0122000000     Skimmed
 0130000000     Latte

人类可读的层次结构:

 0100000000     Coffee
      0110000000     Mocha
      0120000000     Cappuccino
           0121000000     Semi skimmed
                0121100000     Starbuckz
                0121200000     Costa
           0122000000     Skimmed
      0130000000     Latte

我想将此结构转换为如下格式:

 public class LineData
 {
    public string OriginalCode { get; set; }
    public string Title { get; set; }
    public LineData Parent { get; set; }
    public List<LineData> Children { get; set; }
 }

列表是静态的,我可能最终只会存储在内存中。

2 个答案:

答案 0 :(得分:1)

这个怎么样?

var data = " 0100000000     Coffee\r\n 0110000000     Mocha\r\n 0120000000     Cappuccino\r\n 01210" +
    "00000     Semi skimmed\r\n 0121100000     Starbuckz\r\n 0121200000     Costa\r\n 01220" +
    "00000     Skimmed\r\n 0130000000     Latte";
var linesByPrefix = 
    (from l in data.Split(new[]{Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
    let pair = l.Split(new[]{' '},StringSplitOptions.RemoveEmptyEntries)
    select new LineData
    {
        OriginalCode = pair[0],
        Title = pair[1],
        Children = new List<LineData>()
    })
    .ToDictionary(l => l.OriginalCode.TrimEnd('0'));

foreach (var line in linesByPrefix)
{
    var parentCode = line.Key.Substring(0, line.Key.Length - 1);
    LineData parent;
    if(linesByPrefix.TryGetValue(parentCode, out parent))
    {
        line.Value.Parent = parent;
        parent.Children.Add(line.Value);
    }
}
var roots = linesByPrefix.Values.Where(l => l.Parent == null);

答案 1 :(得分:1)

这样的事情可行:

var lines = File.ReadAllLines(@"...");
Stack<LineData> parents = new Stack<LineData>();
List<LineData> items = new List<LineData>();

foreach (string line in lines) 
{
    string[] parts = Regex.Split(line, @"\s+");

    string code = parts[0];
    string title = parts[1];

    LineData newItem = new LineData 
    { 
        OriginalCode = code,
        Title = title
    };

    LineData parent = null;

    // Find the parent, if any.
    while (parents.Any() && parent == null)
    {
        LineData temp = parents.Peek();

        if (code.Replace("0", string.Empty).Contains(
            temp.OriginalCode.Replace("0", string.Empty)))
        {
            parent = temp;
        }
        else
        {
            parents.Pop();
        }
    }

    if (parent != null)
    {
        parent.Children.Add(newItem);
    }
    else 
    {
        items.Add(newItem);
    }

    parents.Push(newItem);
}

基本上遍历每一行并保持一堆祖先不断Pop,直到找到正确的父级。我已将“正确的父级”定义为具有OriginalCode的祖先,该OriginalCode包含在当前项目的LineData中,减去零。

请注意,您还必须为Children添加一个初始化{{1}}的构造函数。