如何将具有相同值的多行列表连接成单行
How to concatenate multiple rows list with same value into single row
我有以下 class 称为“人”。
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Hobby { get; set; }
}
我创建了一个包含以下数据的列表:
List<Person> users = new List<Person>()
{
new Person {Id= 1, Name = "Silva", Hobby = "Football" },
new Person {Id= 2, Name = "Bob", Hobby = "Golf"},
new Person {Id= 2, Name = "Bob", Hobby = "Tennis"},
new Person {Id= 1, Name = "Silva", Hobby = "Sleeping"},
new Person {Id= 3, Name = "Sue", Hobby = "Drinking"}
new Person {Id= 1, Name = "Silva", Hobby = "Handball"},
new Person {Id= 3, Name = "Sue", Hobby = "Football"},
};
现在我需要创建一个名为“usersHobbies”的新列表,调用时 returns 会出现以下结果。
Id Name Hobby
1 Silva Football, Sleeping, Handball
2 Bob Golf, Tennis
3 Sue Drinking, Football
您可以使用 GroupBy()
来实现。按第一组中的 Id
、select 和 Name
分组,使用 string.Join()
将兴趣爱好合并为一个字符串:
var result = users.GroupBy(u => u.Id) // group by Id
.Select(g => new // select values
{
Id = g.Key,
Name = g.First().Name,
Hobbies = string.Join(", ", g.Select(u => u.Hobby))
})
.ToList();
输出:
如果您想 return 一个新的 Person
而不是匿名类型,只需更新 Select
:
.Select(g => new Person
{
Id = g.Key,
Name = g.First().Name,
Hobby = string.Join(", ", g.Select(u => u.Hobby))
})
根据您的评论更新:
is it possible instead of string.join() to return a list or array
是的,是的。使用匿名类型:
var result = users.GroupBy(u => u.Id) // group by Id
.Select(g => new // select values
{
Id = g.Key,
Name = g.First().Name,
Hobbies = g.Select(u => u.Hobby).ToList()
})
.ToList();
其中 return 是 List<string>
for Hobbies
。
.GroupBy()
有一个覆盖,可让您定义键选择器、元素选择器和结果选择器 (docs),这可能适合您的用例:
var result = users
.GroupBy(
u => new { u.Id, u.Name }, // key selector
u => u.Hobby, // element selector
(user, hobbies) => new Person {
Id = user.Id,
Name = user.Name,
Hobby = string.Join(", ", hobbies) })
.ToList();
这里,(user, hobbies)
分别引用键选择器和元素选择器。
发生的事情是:
- 根据
Id
和 Name
(键选择器)的组合将用户分组为唯一用户
- 每个独特用户的爱好被收集到一个
IEnumerable<string>
(元素选择器)
- 对于每个唯一用户,都会创建一个
Person
对象并填充所有用户的爱好。
我有以下 class 称为“人”。
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Hobby { get; set; }
}
我创建了一个包含以下数据的列表:
List<Person> users = new List<Person>()
{
new Person {Id= 1, Name = "Silva", Hobby = "Football" },
new Person {Id= 2, Name = "Bob", Hobby = "Golf"},
new Person {Id= 2, Name = "Bob", Hobby = "Tennis"},
new Person {Id= 1, Name = "Silva", Hobby = "Sleeping"},
new Person {Id= 3, Name = "Sue", Hobby = "Drinking"}
new Person {Id= 1, Name = "Silva", Hobby = "Handball"},
new Person {Id= 3, Name = "Sue", Hobby = "Football"},
};
现在我需要创建一个名为“usersHobbies”的新列表,调用时 returns 会出现以下结果。
Id Name Hobby
1 Silva Football, Sleeping, Handball
2 Bob Golf, Tennis
3 Sue Drinking, Football
您可以使用 GroupBy()
来实现。按第一组中的 Id
、select 和 Name
分组,使用 string.Join()
将兴趣爱好合并为一个字符串:
var result = users.GroupBy(u => u.Id) // group by Id
.Select(g => new // select values
{
Id = g.Key,
Name = g.First().Name,
Hobbies = string.Join(", ", g.Select(u => u.Hobby))
})
.ToList();
输出:
如果您想 return 一个新的 Person
而不是匿名类型,只需更新 Select
:
.Select(g => new Person
{
Id = g.Key,
Name = g.First().Name,
Hobby = string.Join(", ", g.Select(u => u.Hobby))
})
根据您的评论更新:
is it possible instead of string.join() to return a list or array
是的,是的。使用匿名类型:
var result = users.GroupBy(u => u.Id) // group by Id
.Select(g => new // select values
{
Id = g.Key,
Name = g.First().Name,
Hobbies = g.Select(u => u.Hobby).ToList()
})
.ToList();
其中 return 是 List<string>
for Hobbies
。
.GroupBy()
有一个覆盖,可让您定义键选择器、元素选择器和结果选择器 (docs),这可能适合您的用例:
var result = users
.GroupBy(
u => new { u.Id, u.Name }, // key selector
u => u.Hobby, // element selector
(user, hobbies) => new Person {
Id = user.Id,
Name = user.Name,
Hobby = string.Join(", ", hobbies) })
.ToList();
这里,(user, hobbies)
分别引用键选择器和元素选择器。
发生的事情是:
- 根据
Id
和Name
(键选择器)的组合将用户分组为唯一用户 - 每个独特用户的爱好被收集到一个
IEnumerable<string>
(元素选择器) - 对于每个唯一用户,都会创建一个
Person
对象并填充所有用户的爱好。