C# LINQ-按多个列分组并合并结果
我正在处理相当大的一组数据(~130000条记录),我已经设法以我想要的方式将其转换为csv 下面是列表的简化示例: 现在,如果第1列、第2列和第3列匹配,我想合并这些记录,如下所示: 输出C# LINQ-按多个列分组并合并结果,c#,linq,C#,Linq,我正在处理相当大的一组数据(~130000条记录),我已经设法以我想要的方式将其转换为csv 下面是列表的简化示例: 现在,如果第1列、第2列和第3列匹配,我想合并这些记录,如下所示: 输出 "Surname1, Name1;Address1;State1;YES;Group1" "Surname2, Name2;Address2;State2;YES;Group2 Group1" "Surname3, Name3;Address3;State3
"Surname1, Name1;Address1;State1;YES;Group1"
"Surname2, Name2;Address2;State2;YES;Group2 Group1"
"Surname3, Name3;Address3;State3;NO;Group1"
"Surname1, Name1;Address2;State1;YES;Group1"
以下是到目前为止我得到的信息:
output.GroupBy(x => new { c1 = x.Split(';')[0], c2 = x.Split(';')[1], c3 = x.Split(';')[2] }).Select(//have no idea what should go here);
首先尝试获取以匿名类型投影结果所需的列:
var query= from r in output
let columns= r.Split(';')
select new { c1 =columns[0], c2 =columns[1], c3 = columns[2] ,c5=columns[4]};
然后创建组,但现在使用在上一个查询中定义的匿名对象:
var result= query.GroupBy(e=>new {e.c1, e.c2, e.c3})
.Select(g=> new {SurName=g.Key.c1,
Name=g.Key.c2,
Address=g.Key.c3,
Groups=String.Join(",",g.Select(e=>e.c4)});
我知道我遗漏了一些专栏,但我想你可以理解
PS:我在两个查询中分离逻辑的事实只是为了可读性,您可以在一个查询中组合两个查询,但这不会改变性能,因为LINQ使用 首先尝试获取以匿名类型投影结果所需的列:
var query= from r in output
let columns= r.Split(';')
select new { c1 =columns[0], c2 =columns[1], c3 = columns[2] ,c5=columns[4]};
然后创建组,但现在使用在上一个查询中定义的匿名对象:
var result= query.GroupBy(e=>new {e.c1, e.c2, e.c3})
.Select(g=> new {SurName=g.Key.c1,
Name=g.Key.c2,
Address=g.Key.c3,
Groups=String.Join(",",g.Select(e=>e.c4)});
我知道我遗漏了一些专栏,但我想你可以理解
PS:我在两个查询中分离逻辑的事实只是为了可读性,您可以在一个查询中组合两个查询,但这不会改变性能,因为LINQ使用 我会这样做:
class Program
{
static void Main(string[] args)
{
List<string> input = new List<string> {
"Surname1, Name1;Address1;State1;YES;Group1",
"Surname2, Name2;Address2;State2;YES;Group2",
"Surname2, Name2;Address2;State2;YES;Group1",
"Surname3, Name3;Address3;State3;NO;Group1",
"Surname1, Name1;Address2;State1;YES;Group1",
};
var transformed = input.Select(s => s.Split(';'))
.GroupBy( s => new string[] { s[0], s[1], s[2], s[3] },
(key, elements) => string.Join(";", key) + ";" + string.Join(" ", elements.Select(e => e.Last())),
new MyEqualityComparer())
.ToList();
}
}
internal class MyEqualityComparer : IEqualityComparer<string[]>
{
public bool Equals(string[] x, string[] y)
{
return x[0] == y[0] && x[1] == y[1] && x[2] == y[2];
}
public int GetHashCode(string[] obj)
{
int hashCode = obj[0].GetHashCode();
hashCode = hashCode ^ obj[1].GetHashCode();
hashCode = hashCode ^ obj[2].GetHashCode();
return hashCode;
}
}
类程序
{
静态void Main(字符串[]参数)
{
列表输入=新列表{
“姓1,名1;地址1;状态1;是;组1”,
“姓2,名2;地址2;状态2;是;组2”,
“姓2,名2;地址2;状态2;是;组1”,
“姓氏3,姓名3;地址3;状态3;编号;组1”,
“姓1,名1;地址2;状态1;是;组1”,
};
var transformed=input.Select(s=>s.Split(';'))
.GroupBy(s=>新字符串[]{s[0],s[1],s[2],s[3]},
(key,elements)=>string.Join(“;”,key)+“;”+string.Join(“,elements.Select(e=>e.Last()),
新建MyEqualityComparer())
.ToList();
}
}
内部类MyEqualityComparer:IEqualityComparer
{
公共布尔等于(字符串[]x,字符串[]y)
{
返回x[0]==y[0]&&x[1]==y[1]&&x[2]==y[2];
}
public int GetHashCode(字符串[]obj)
{
int hashCode=obj[0].GetHashCode();
hashCode=hashCode^obj[1]。GetHashCode();
hashCode=hashCode^obj[2]。GetHashCode();
返回哈希码;
}
}
将前4列视为分组键,但仅使用前3列进行比较(因此使用自定义IEqualityComparer
)。
然后,如果您有(键,元素)组,则对其进行变换,以便将键的元素与;(请记住,键由前4列组成)并将组中每个成员的最后一个元素添加到其中,并用空格连接。我将这样做:
class Program
{
static void Main(string[] args)
{
List<string> input = new List<string> {
"Surname1, Name1;Address1;State1;YES;Group1",
"Surname2, Name2;Address2;State2;YES;Group2",
"Surname2, Name2;Address2;State2;YES;Group1",
"Surname3, Name3;Address3;State3;NO;Group1",
"Surname1, Name1;Address2;State1;YES;Group1",
};
var transformed = input.Select(s => s.Split(';'))
.GroupBy( s => new string[] { s[0], s[1], s[2], s[3] },
(key, elements) => string.Join(";", key) + ";" + string.Join(" ", elements.Select(e => e.Last())),
new MyEqualityComparer())
.ToList();
}
}
internal class MyEqualityComparer : IEqualityComparer<string[]>
{
public bool Equals(string[] x, string[] y)
{
return x[0] == y[0] && x[1] == y[1] && x[2] == y[2];
}
public int GetHashCode(string[] obj)
{
int hashCode = obj[0].GetHashCode();
hashCode = hashCode ^ obj[1].GetHashCode();
hashCode = hashCode ^ obj[2].GetHashCode();
return hashCode;
}
}
类程序
{
静态void Main(字符串[]参数)
{
列表输入=新列表{
“姓1,名1;地址1;状态1;是;组1”,
“姓2,名2;地址2;状态2;是;组2”,
“姓2,名2;地址2;状态2;是;组1”,
“姓氏3,姓名3;地址3;状态3;编号;组1”,
“姓1,名1;地址2;状态1;是;组1”,
};
var transformed=input.Select(s=>s.Split(';'))
.GroupBy(s=>新字符串[]{s[0],s[1],s[2],s[3]},
(key,elements)=>string.Join(“;”,key)+“;”+string.Join(“,elements.Select(e=>e.Last()),
新建MyEqualityComparer())
.ToList();
}
}
内部类MyEqualityComparer:IEqualityComparer
{
公共布尔等于(字符串[]x,字符串[]y)
{
返回x[0]==y[0]&&x[1]==y[1]&&x[2]==y[2];
}
public int GetHashCode(字符串[]obj)
{
int hashCode=obj[0].GetHashCode();
hashCode=hashCode^obj[1]。GetHashCode();
hashCode=hashCode^obj[2]。GetHashCode();
返回哈希码;
}
}
将前4列视为分组键,但仅使用前3列进行比较(因此使用自定义IEqualityComparer
)。
然后,如果您有(键,元素)组,则对其进行变换,以便将键的元素与;(请记住,键由前4列组成)并将组中每个成员的最后一个元素添加到键中,并用空格连接