我有Foo
类型的对象列表。每个Foo
对象都包含对其父级的引用:
public class Foo
{
public Foo Parent { get; set; }
}
(如果Parent
为空,则Foo
被视为“根”节点。)如您所见,这意味着一种“自下而上”的树层次结构。 / p>
我想通过将Foo
个对象包装在一个名为TreeItem
的新类中来颠倒这个子 - >父级关联;
public class TreeItem<T>
{
public T Item { get; set; }
public IEnumerable<TreeItem<T>> Children { get; set; }
}
如图所示,这将给我一个更自然的“自上而下”树层次结构。我相信这将允许更容易的数据绑定,例如。在WPF中TreeView
。
是否有一个简明的Linq语句可以获取List<Foo>
,找到每个Foo
对象的子项,并吐出相应转换的TreeItem<Foo>
列表?
除了Linq查询,最简单的算法是什么?
奖金 :您将使用哪些字词或搜索字词来描述这种“树翻转”转换?
答案 0 :(得分:6)
ToLookup
可以轻松地为每个项目创建所有子项的查找。完成后,您可以将每个项目映射到新对象,并有一个简单的机制来获取每个项目的所有子项。
IEnumerable<Foo> data = GetData();
var lookup = data.ToLookup(foo => foo.Parent);
Func<Foo, TreeItem<object>> selector = null;
selector = foo => new TreeItem<object>()
{
Item = foo,
Children = lookup[foo].Select(selector),
};
var rootNodes = lookup[null].Select(selector);
或者,如果你宁愿避免递归,你可以在构建查找时转换每个项目而不映射子项,然后改变每个项目以便以后包含子项:
IEnumerable<Foo> data = GetData();
var lookup = data.ToLookup(foo => foo.Parent,
foo => new TreeItem<object>() { Item = foo });
foreach (var node in lookup.SelectMany(x => x))
node.Children = lookup[node.Item];
var rootNodes = lookup[null];
如果存在大量数据,则缺少递归可能很重要,并且它还允许它处理任意图形,而不仅仅是树。 (特别是它可以处理循环。)