【问题标题】:How to find Distinc from the multiple lists using LINQ?如何使用 LINQ 从多个列表中查找 Distinct?
【发布时间】:2021-04-07 11:05:27
【问题描述】:

我需要从整个国家集合中找到所有不同的项目(宗教),其中每个国家都有自己的项目(宗教)列表。这是我的对象类:

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)}";
     }  

这是我的主要课程:

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 函数内部或在我的打印输出函数内部。任何帮助将不胜感激。这是打印输出:

【问题讨论】:

  • 两者。 Distinct() 操作仅适用于匿名对象,而不适用于它们的内容。所有这些对象都是独一无二的,所以Distinct() 什么都不做。 Console.WriteLine 作用于匿名对象,而不是 Religions 属性的内容。

标签: c# list linq distinct


【解决方案1】:

两者都是错误的。两者都适用于匿名对象,而不是宗教字符串。

要获得不同的宗教,您需要使用 SelectMany 来“拉平”国家/宗教图表:

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

【讨论】:

    【解决方案2】:

    这里有几个问题。

    1. 您认为使用.Select(r =&gt; new { r.Religions }) 会得到什么 - 它会为您提供列表列表。您想要的是SelectMany(r =&gt; r.Religions) - 这样,您将获得宗教列表,而不是其属性中包含列表的匿名对象列表。

    2. Distinct 使用基本比较,您需要编写自定义比较器并提供给重载:

    Distinct<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
    

    你需要实现IEqualityComparer&lt;Religion&gt;

    更新:宗教只是一个字符串,所以你不需要实现一个,使用SelectMany之后一切都应该没问题。

    1. 您的“打印输出”功能 - 您使用 Console.WriteLine,它仅在对象上调用 ToString - 因为那里有列表,它看起来很奇怪 :) 在建议使用 SelectMany 后,它应该会消失。

    【讨论】:

      猜你喜欢
      • 2020-04-27
      • 1970-01-01
      • 1970-01-01
      • 2011-05-01
      • 1970-01-01
      • 2021-02-16
      • 1970-01-01
      • 1970-01-01
      • 2019-10-17
      相关资源
      最近更新 更多