Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用LINQ规范化数据_Linq_Normalization - Fatal编程技术网

使用LINQ规范化数据

使用LINQ规范化数据,linq,normalization,Linq,Normalization,假设我们有一些非规范化数据,如下所示: List<string[]> dataSource = new List<string[]>(); string [] row1 = {"grandParentTitle1", "parentTitle1", "childTitle1"}; string [] row2 = {"grandParentTitle1", "parentTitle1", "childTitle2"}; string [] row3 = {"grandP

假设我们有一些非规范化数据,如下所示:

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);
List dataSource=newlist();
字符串[]行1={“祖父母标题1”、“父母标题1”、“子女标题1”};
字符串[]行2={“祖父母标题1”、“父母标题1”、“子女标题2”};
字符串[]行3={“祖父母标题1”、“父母标题2”、“子女标题3”};
字符串[]行4={“祖父母标题1”、“父母标题2”、“子女标题4”};
dataSource.Add(第1行);
我需要对其进行规范化,例如,使用Child.Parent和Child.Parent.祖父母填充IEnumerable

命令式的方式或多或少是清楚的。林克会缩短吗

在一个查询中效果更好,应该可以扩展到更多实体

我尝试了像分别创建IEnumerable,然后使用赋值等方法创建IEnumerable


请给出一个提示,这可以通过功能性的方式实现吗?

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());

我不认为这比命令式版本读起来更好。

最基本的方法是使用匿名变量:

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
的子类。然后你可以这样做:

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])));
这两种解决方案中有一种适合您吗


如果您想要不同的
祖父母
父母
子女
类型,那么您应该能够修改最后一个示例以适应。

您可以使用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);
    }
}

问题是如何创建和链接实体,而不使用重复项。选择(新父母{祖父母=新祖父母}),否则我会错过什么?