假设我们有一些非规范化数据,如下所示:
List<string[]> dataSource = new List<string[]>();
string [] row1 = {"grandParentTitle1", "parentTitle1", "childTitle1"};
string [] row2 = {"grandParentTitle1", "parentTitle1", "childTitle2"};
string [] row3 = {"grandParentTitle1", "parentTitle2", "childTitle3"};
string [] row4 = {"grandParentTitle1", "parentTitle2", "childTitle4"};
dataSource.Add(row1);
我需要将其标准化,例如得到IEnumerable&lt;小孩&gt;填充Child.Parent和Child.Parent.GrandParent。
势在必行的方式或多或少都很明确。 Linq会缩短吗?
在一个查询中更好,对于更多实体,这应该是可扩展的。
我试过像分开创建IEnumerable&lt; GrandParent&gt ;,然后IEnumerable&lt;父母&gt;分配等。
PLease能否以功能性的方式实现这一点?
答案 0 :(得分:1)
您可以使用group by完成您想要的操作。不幸的是我对C#LINQ语法的了解是有限的,所以我只能告诉你调用扩展方法GroupBy的方式。
var normalized = dataSource
.GroupBy(source => source[0], (grandParent, grandParentChilds) => new { GrandParent = grandParent, Parents = grandParentChilds
.GroupBy(source => source[1], (parent, parentChilds) => new { Parent = parent, Children = from source in parentChilds select source[2]}) });
foreach (var grandParent in normalized)
{
Console.WriteLine("GrandParent: {0}", grandParent.GrandParent);
foreach (var parent in grandParent.Parents)
{
Console.WriteLine("\tParent: {0}", parent.Parent);
foreach (string child in parent.Children)
Console.WriteLine("\t\tChild: {0}", child);
}
}
答案 1 :(得分:0)
Linq确实与此相反。即。如果你将它标准化,你可以很容易地说
from g in grandParents
from p in g.Parents
from c in p.Children
select new { GrandParentName = g.Name, ParentName = p.Name, ChildName = c.Name };
做你要问的事情比较棘手。像这样的东西
var grandparents = (from g in dataSource
select new GrandParent {
Title = g[0],
Parents = (from p in dataSource
where p[0] == g[0]
select new Parent {
Title = p[1],
Children = from c in dataSource
where p[1] == c[1]
select new
{
Title = c[2]
}
}).Distinct(new ParentTitleComparer())
}).Distinct(new GrandParentTitleComparer());
我不相信这比命令式版本更好。
答案 2 :(得分:0)
执行此操作的最基本方法是使用匿名变量:
from ds0 in dataSource group ds0 by ds0[0] into grandparents
select new
{
Grandparent = grandparents.Key,
Parents =
from ds1 in grandparents group ds1 by ds1[1] into parents
select new
{
Parent = parents.Key,
Children = from ds2 in parents select ds2[2]
}
};
如果你想用具体的类做这个,我建议创建一个带有构造函数的Person
类,该构造函数使用IEnumerable<Person>
代表正在构造的Person
的子代。然后你可以这样做:
from ds0 in dataSource
group ds0 by ds0[0] into grandparents
select new Person(grandparents.Key,
from ds1 in grandparents
group ds1 by ds1[1] into parents
select new Person(parents.Key,
from ds2 in parents
select new Person(ds2[2])));
这些解决方案中的任何一个都适合您吗?
如果您想要不同的GrandParent
,Parent
&amp; Child
类型,那么您应该能够修改最后一个示例以适应。