如果我有一个具有父子关系的对象,Id和ParentId表示记录的唯一ID和记录的父ID。
我需要一个查询对象列表的查询,并返回每个项目关系根目录的路径(即Path =(AllTheParentNames)\ Name)。
对此有任何帮助将不胜感激。
int Id
诠释?的ParentId
字符串名称
字符串路径
答案 0 :(得分:4)
我相信这会给你预期的结果
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
答案 1 :(得分:2)
首先,假设您有一个节点。您希望获得根路径。
让我们将根路径表示为一系列节点。
我们可以构建一个写一个方法,该方法接受一个项和一个标识下一个项的函数,并返回序列。
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);
}
}
现在,您可以在对象列表中编写查询。
List<Node> nodes = whatever;
var paths = from node in nodes
select Path(node, n=>GetNodeById(n.Parent));
现在你有了一系列节点序列。
假设您需要一系列字符串序列:
var namePaths =
from node in nodes
select (from pathElement in Path(node, n=>GetNodeById(n.Parent))
select pathElement.Name);
等等。
有意义吗?
答案 2 :(得分:1)
这是预期的结果吗?
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();
}
}
没有递归就不可能在单个查询中生成(数组上的foreach(Aggregate)可能对模拟递归有好处,但它很愚蠢)
修复 - 是Fixed point combinator