如何使用 LINQ 从多个列表中找到 Distinct?
How to find Distinc from the multiple lists using LINQ?
我需要从整个国家集合中找到所有不同的项目(宗教),其中每个国家都有自己的项目(宗教)列表。这是我的对象 class:
public class Country
{
public string Name { get; }
public List<string> Religions { get; }
public Country(string name, List<string> religions)
{
Name = name;
Religions = religions;
}
public static List<Country> GetCountries()
{
return new List<Country>()
{
new Country( "Venezuela", new List<string> { "Roman Catholic", "Protestant" } ),
new Country( "Peru", new List<string> { "Roman Catholic", "Evangelical" } ),
new Country( "Paraguay", new List<string> { "Roman Catholic", "Protestant" } ),
new Country( "Bolivia", new List<string> { "Roman Catholic", "Evangelical", "Protestant" } )
};
}
public override string ToString() =>
$"\n{Name} \nReligions: {string.Join(", ", Religions)}";
}
这是我的主要内容 class:
List<Country> countries = Country.GetCountries();
AllReligions(countries);
Console.ReadKey();
static void AllReligions(List<Country> countries)
{
var distinctReligions = countries
.Select(r => new { r.Religions })
.Distinct()
.ToList();
Console.WriteLine("Religions in South America:");
foreach (var rel in distinctReligions)
Console.WriteLine(rel);
}
我正在对代码进行第 5 次迭代,其中一个问题是我不知道错误发生在何处 - 在我的 DISTINCT 函数内或在我的打印输出函数内。任何帮助将不胜感激。这是打印输出:
两者都错了。两者都适用于匿名对象,而不适用于宗教字符串。
要获得不同的宗教,您需要使用 SelectMany 来“扁平化”country/religion 图表:
IEnumerable<string> religions=Country
.GetCountries()
.SelectMany(country=>country.Religions)
.Distinct();
Console.WriteLine("Religions in South America:");
foreach (var rel in religions)
{
Console.WriteLine(rel);
}
查询形式的等价物是:
var religions = ( from country in Country.GetCountries()
from religion in country.Religions
select religion
).Distinct();
你这里有几个问题。
您认为使用 .Select(r => new { r.Religions })
得到的结果 - 它为您提供列表列表。您想要的是 SelectMany(r => r.Religions)
- 这样,您将获得宗教列表,而不是在其 属性.
中包含列表的匿名对象列表
Distinct
使用基本比较,需要自己写自定义比较器提供重载:
Distinct<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
您需要实施 IEqualityComparer<Religion>
。
更新:宗教只是一个字符串,所以你不需要实现一个,在使用 SelectMany
之后一切都应该很好。
- 你的“打印输出”功能 - 你使用
Console.WriteLine
只调用对象上的 ToString
- 因为你有列表,它看起来很奇怪 :) 在建议使用 SelectMany
之后应该离开。
我需要从整个国家集合中找到所有不同的项目(宗教),其中每个国家都有自己的项目(宗教)列表。这是我的对象 class:
public class Country
{
public string Name { get; }
public List<string> Religions { get; }
public Country(string name, List<string> religions)
{
Name = name;
Religions = religions;
}
public static List<Country> GetCountries()
{
return new List<Country>()
{
new Country( "Venezuela", new List<string> { "Roman Catholic", "Protestant" } ),
new Country( "Peru", new List<string> { "Roman Catholic", "Evangelical" } ),
new Country( "Paraguay", new List<string> { "Roman Catholic", "Protestant" } ),
new Country( "Bolivia", new List<string> { "Roman Catholic", "Evangelical", "Protestant" } )
};
}
public override string ToString() =>
$"\n{Name} \nReligions: {string.Join(", ", Religions)}";
}
这是我的主要内容 class:
List<Country> countries = Country.GetCountries();
AllReligions(countries);
Console.ReadKey();
static void AllReligions(List<Country> countries)
{
var distinctReligions = countries
.Select(r => new { r.Religions })
.Distinct()
.ToList();
Console.WriteLine("Religions in South America:");
foreach (var rel in distinctReligions)
Console.WriteLine(rel);
}
我正在对代码进行第 5 次迭代,其中一个问题是我不知道错误发生在何处 - 在我的 DISTINCT 函数内或在我的打印输出函数内。任何帮助将不胜感激。这是打印输出:
两者都错了。两者都适用于匿名对象,而不适用于宗教字符串。
要获得不同的宗教,您需要使用 SelectMany 来“扁平化”country/religion 图表:
IEnumerable<string> religions=Country
.GetCountries()
.SelectMany(country=>country.Religions)
.Distinct();
Console.WriteLine("Religions in South America:");
foreach (var rel in religions)
{
Console.WriteLine(rel);
}
查询形式的等价物是:
var religions = ( from country in Country.GetCountries()
from religion in country.Religions
select religion
).Distinct();
你这里有几个问题。
您认为使用
中包含列表的匿名对象列表.Select(r => new { r.Religions })
得到的结果 - 它为您提供列表列表。您想要的是SelectMany(r => r.Religions)
- 这样,您将获得宗教列表,而不是在其 属性.Distinct
使用基本比较,需要自己写自定义比较器提供重载:
Distinct<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
您需要实施 IEqualityComparer<Religion>
。
更新:宗教只是一个字符串,所以你不需要实现一个,在使用 SelectMany
之后一切都应该很好。
- 你的“打印输出”功能 - 你使用
Console.WriteLine
只调用对象上的ToString
- 因为你有列表,它看起来很奇怪 :) 在建议使用SelectMany
之后应该离开。