C# Linq查询难题

C# Linq查询难题,c#,linq,C#,Linq,如果我有一个具有父子关系的对象,其Id和ParentId表示记录的唯一Id和记录的父Id 我需要一个查询,该查询将查询对象列表并返回每个项的关系根的路径,即path=AllTheParentNames\Name 在此方面的任何帮助都将不胜感激 肌体 整数Id 智力?父ID 字符串名 字符串路径我相信这将为您提供预期的结果 Func<int?, string> GetParents = null; List<URClass> lstRoot

如果我有一个具有父子关系的对象,其Id和ParentId表示记录的唯一Id和记录的父Id

我需要一个查询,该查询将查询对象列表并返回每个项的关系根的路径,即path=AllTheParentNames\Name

在此方面的任何帮助都将不胜感激

肌体 整数Id 智力?父ID 字符串名
字符串路径

我相信这将为您提供预期的结果

        Func<int?, string> GetParents = null;

        List<URClass> lstRoot = new List<URClass>();
        lstRoot.Add(new URClass() { Id = 1, Name = "a", ParentId = null, Path = "1" });
        lstRoot.Add(new URClass() { Id = 2, Name = "b", ParentId = 1, Path = "1" });
        lstRoot.Add(new URClass() { Id = 3, Name = "c", ParentId = 2, Path = "1" });
        lstRoot.Add(new URClass() { Id = 4, Name = "d", ParentId = 3, Path = "1" });
        lstRoot.Add(new URClass() { Id = 5, Name = "e", ParentId = 4, Path = "1" });

        GetParents = i =>
        {
            var str = string.Empty;
            var outt = lstRoot.Where(x => x.Id == i).Select(x=>new {x.Name,x.ParentId });

            foreach (var lst in outt)
            {
                str += lst.Name;
                if (lst.ParentId != null)
                {
                      var outts = GetParents(lst.ParentId);
                      str += "," + outts;
                }                    
            }
            return str;

        };          

        var ks = from p in lstRoot
                 join q in lstRoot on p.Id equals q.ParentId
                 select new { q.Id, parentName = p.Name, parentid=p.Id, gpid=p.ParentId };


        List<string> RelationShip = new List<string>();

        foreach (var lst in ks)
        {
            var str = lst.parentName;
            if (lst.gpid != null)
            {
                 var prnt = GetParents(lst.gpid);
                 if (prnt != null)
                    str += "," + prnt;                   
            }
            str += "/" + lst.Id;
            RelationShip.Add(str); 
        }


        foreach (var ret in RelationShip)
            Console.WriteLine(ret);
输出将是

a/2

b、 a/3

c、 b,a/4

d、 c、b、a/5


我相信这会给你预期的结果

        Func<int?, string> GetParents = null;

        List<URClass> lstRoot = new List<URClass>();
        lstRoot.Add(new URClass() { Id = 1, Name = "a", ParentId = null, Path = "1" });
        lstRoot.Add(new URClass() { Id = 2, Name = "b", ParentId = 1, Path = "1" });
        lstRoot.Add(new URClass() { Id = 3, Name = "c", ParentId = 2, Path = "1" });
        lstRoot.Add(new URClass() { Id = 4, Name = "d", ParentId = 3, Path = "1" });
        lstRoot.Add(new URClass() { Id = 5, Name = "e", ParentId = 4, Path = "1" });

        GetParents = i =>
        {
            var str = string.Empty;
            var outt = lstRoot.Where(x => x.Id == i).Select(x=>new {x.Name,x.ParentId });

            foreach (var lst in outt)
            {
                str += lst.Name;
                if (lst.ParentId != null)
                {
                      var outts = GetParents(lst.ParentId);
                      str += "," + outts;
                }                    
            }
            return str;

        };          

        var ks = from p in lstRoot
                 join q in lstRoot on p.Id equals q.ParentId
                 select new { q.Id, parentName = p.Name, parentid=p.Id, gpid=p.ParentId };


        List<string> RelationShip = new List<string>();

        foreach (var lst in ks)
        {
            var str = lst.parentName;
            if (lst.gpid != null)
            {
                 var prnt = GetParents(lst.gpid);
                 if (prnt != null)
                    str += "," + prnt;                   
            }
            str += "/" + lst.Id;
            RelationShip.Add(str); 
        }


        foreach (var ret in RelationShip)
            Console.WriteLine(ret);
输出将是

a/2

b、 a/3

c、 b,a/4

d、 c、b、a/5


这是预期的结果吗

class A
{
    public int Id;
    public int? ParentId;
    public string Name;


    public static Func<T1, T2> Fix<T1, T2>(Func<Func<T1, T2>, Func<T1, T2>> f)
    {
        return f(x => Fix(f)(x));
    }

    public static string[] GetPaths(A[] array)
    {
        return array.Select(
            Fix<A, string>(self => x => x.ParentId != null ? self(array.First(a => a.Id == x.ParentId.Value)) + "\\" + x.Name : x.Name)
            ).ToArray();
    }
}
在单个查询中不可能不使用递归,因为数组上的每个聚合可能有助于模拟递归,但它很愚蠢


修复-这是预期结果吗

class A
{
    public int Id;
    public int? ParentId;
    public string Name;


    public static Func<T1, T2> Fix<T1, T2>(Func<Func<T1, T2>, Func<T1, T2>> f)
    {
        return f(x => Fix(f)(x));
    }

    public static string[] GetPaths(A[] array)
    {
        return array.Select(
            Fix<A, string>(self => x => x.ParentId != null ? self(array.First(a => a.Id == x.ParentId.Value)) + "\\" + x.Name : x.Name)
            ).ToArray();
    }
}
在单个查询中不可能不使用递归,因为数组上的每个聚合可能有助于模拟递归,但它很愚蠢


Fix-是第一个节点,假设您有一个节点。您希望获得根目录的路径

让我们将根的路径表示为一系列节点

我们可以构建这个函数,编写一个方法,该方法接受一个项和一个函数,该函数标识下一个项,并返回序列

public static IEnumerable<T> Path(T item, Func<T, T> nextItem) where T : class
{
    T current = item;
    while(current != null)
    {
        yield return current;
        current = nextItem(current);
    }
}
等等


有意义吗?

首先,假设您有一个节点。您希望获得根目录的路径

让我们将根的路径表示为一系列节点

我们可以构建这个函数,编写一个方法,该方法接受一个项和一个函数,该函数标识下一个项,并返回序列

public static IEnumerable<T> Path(T item, Func<T, T> nextItem) where T : class
{
    T current = item;
    while(current != null)
    {
        yield return current;
        current = nextItem(current);
    }
}
等等


有意义吗?

为什么你认为这是家庭作业?即使那是什么事?除非是建设性的,否则为什么要说。为什么你认为这是家庭作业?即使那是什么事?除非是建设性的,否则为什么要说任何话。这看起来像是很多代码来实现我的期望。@Burt,是的,当然。。但它给出了预期的结果。。我也在学习lambdas&linq,这就是原因。。无论如何,我现在正在重构代码:看起来有很多代码可以实现我的期望。@Burt,是的,当然。。但它给出了预期的结果。。我也在学习lambdas&linq,这就是原因。。无论如何,我现在正在重构代码: