如何展平自引用查询?

时间:2016-10-16 07:44:24

标签: c# linq

似乎这种情况已经得到了回答,但我无法找到它 我有下表:

Id     Parent     Text
-----------------------
1      NULL       A
2       1         B
3       2         C
4       3         D
5      NULL       E
6       5         F
7       6         G

现在我希望得到如下结果:(List<string>

A
A > B
A > B > C
A > B > C > D
E
E > F
E > F > G

但问题是,我正在研究的这个项目首先使用数据库,我的意思是没有导航属性,Parent类型为string而不是IEnumerable<T>

到目前为止我做了什么:

var list = new List<string>();
string e2 = string.Empty;
foreach (var item in query)
{
    string e1 = string.Empty;
    if (item.Parent == null)
    {
        list.Add(p.Text);
        e2 = item.Text;
    }
    else
    {
        foreach (var subItem in query.Where(t => t.Id == p.Parent))
        {
            if (subItem.Id != 1)
            {
                e1 = e2 + " > " + subItem.Text;
            }
            else
            {
                e1 = subItem.Text;
            }
        }
        list.Add(e1 + " > " + p.Text);
    }
}

2 个答案:

答案 0 :(得分:1)

使用递归算法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static List<string> list = new List<string>();
        static DataTable dt = new DataTable();
        static void Main(string[] args)
        {
            dt.Columns.Add("Id", typeof(int));
            dt.Columns.Add("Parent", typeof(int));
            dt.Columns["Parent"].AllowDBNull = true;
            dt.Columns.Add("Text", typeof(string));

            dt.Rows.Add(new object[] {1, null, "A"});
            dt.Rows.Add(new object[] {2, 1, "B"});
            dt.Rows.Add(new object[] {3, 2, "C"});
            dt.Rows.Add(new object[] {4, 3, "D"});
            dt.Rows.Add(new object[] {5, null, "E"});
            dt.Rows.Add(new object[] {6, 5, "F"});
            dt.Rows.Add(new object[] {7, 6, "G"});

            GetRecursiveChildren(null, new List<string>());

            foreach (string row in list)
            {
                Console.WriteLine(row);
            }
            Console.ReadLine();
        }
        static void GetRecursiveChildren(int? parent, List<string> parents)
        {
            foreach (DataRow row in dt.AsEnumerable().Where(x => x.Field<int?>("Parent") == parent))
            {
                string text = row.Field<string>("Text");
                List<string> newParents = new List<string>();
                newParents.AddRange(parents);
                newParents.Add(text);
                list.Add(string.Join(" > ",newParents));
                int child = row.Field<int>("Id");
                GetRecursiveChildren(child, newParents);
            }
        }
    }

}

答案 1 :(得分:1)

这对我有用:

var source = new []
{
    new { Id = 1, Parent = (int?)null, Text = "A" },
    new { Id = 2, Parent = (int?)1, Text = "B" },
    new { Id = 3, Parent = (int?)2, Text = "C" },
    new { Id = 4, Parent = (int?)3, Text = "D" },
    new { Id = 5, Parent = (int?)null, Text = "E" },
    new { Id = 6, Parent = (int?)5, Text = "F" },
    new { Id = 7, Parent = (int?)6, Text = "G" }
};

var lookup = source.ToLookup(x => x.Parent);

Func<int?, IEnumerable<string>> recurse = null;
recurse = p =>
    lookup[p].SelectMany(x => new [] { x.Text }
        .Concat(recurse(x.Id).Select(y => $"{x.Text} > {y}")));

foreach (string x in recurse(null))
{
    Console.WriteLine(x);
}

我明白了:

A
A > B
A > B > C
A > B > C > D
E
E > F
E > F > G