【问题标题】:Join two list comparing their elements properties加入两个列表比较它们的元素属性
【发布时间】:2011-11-13 10:29:53
【问题描述】:
public class Person()
    {
    int ID;
    string Name;
    DateTime ChangeDate
    } 



var list1 = new List<Person>
    {
        new Person { ID= 1, Name = "Peter", ChangeDate= "2011-10-21" },
        new Person { ID= 2, Name = "John",  ChangeDate= "2011-10-22" },
        new Person { ID= 3, Name = "Mike",  ChangeDate= "2011-10-23" },
        new Person { ID= 4, Name = "Dave",  ChangeDate= "2011-10-24" }
    };

 var list2 = new List<Person>
    {
        new Person { ID= 1, Name = "Pete",  ChangeDate= "2011-10-21" },
        new Person { ID= 2, Name = "Johny", ChangeDate= "2011-10-20" },
        new Person { ID= 3, Name = "Mikey", ChangeDate= "2011-10-24" },
        new Person { ID= 5, Name = "Larry", ChangeDate= "2011-10-27" }
    };

作为输出,我想要 list1 + list2 =

    Person { ID= 1, Name = "Peter", ChangeDate= "2011-10-21" },
    Person { ID= 2, Name = "John",  ChangeDate= "2011-10-22" },
    Person { ID= 3, Name = "Mikey", ChangeDate= "2011-10-24" },
    Person { ID= 4, Name = "Dave",  ChangeDate= "2011-10-24" }
    Person { ID= 5, Name = "Larry", ChangeDate= "2011-10-27" }

算法是这样的。 加入两个列表。如果列表的元素具有相同的 ID,则通过 ChangeDate 比较它们并取较大日期的第一个。如果 ChangeDate 相等,则取其中任何一个,但不能同时取两者。 也许连接两个列表比使用 lambda 过滤它们更容易。我试过了,但总是出现一些丑陋的代码:/

有人知道吗?

【问题讨论】:

  • 如果可以的话,我会使用DateTime 而不是字符串值。

标签: c# linq


【解决方案1】:

LINQ

var q = from person in list1.Concat(list2)
        group person by person.ID into g
        select g.OrderByDescending(p => p.ChangeDate).First();

【讨论】:

    【解决方案2】:

    合并两个按降序排序的列表。现在您需要在排序列表中获取每个 id 的第一次出现。

    【讨论】:

      【解决方案3】:

      这样的事情怎么样?

      using System;
      using System.Collections.Generic;
      using System.Linq;
      
      public class Person
      {
          public int ID;
          public string Name;
          public DateTime ChangeDate;
      }
      
      public class PersonComparer : IEqualityComparer<Person>
      {
          public bool Equals(Person p1, Person p2)
          {
              return p1.ID == p2.ID;
          }
      
          public int GetHashCode(Person p)
          {
              return p.ID.GetHashCode();
          }
      }
      
      class Program
      {
          static void Main(string[] args)
          {
              var list1 = new List<Person>
              {
                  new Person { ID = 1, Name = "Peter", ChangeDate = DateTime.Parse("2011-10-21") },
                  new Person { ID = 2, Name = "John",  ChangeDate = DateTime.Parse("2011-10-22") },
                  new Person { ID = 3, Name = "Mike",  ChangeDate = DateTime.Parse("2011-10-23") },
                  new Person { ID = 4, Name = "Dave",  ChangeDate = DateTime.Parse("2011-10-24") }
              };
      
              var list2 = new List<Person>
              {
                  new Person { ID = 1, Name = "Pete",  ChangeDate = DateTime.Parse("2011-10-21") },
                  new Person { ID = 2, Name = "Johny", ChangeDate = DateTime.Parse("2011-10-20") },
                  new Person { ID = 3, Name = "Mikey", ChangeDate = DateTime.Parse("2011-10-24") },
                  new Person { ID = 5, Name = "Larry", ChangeDate = DateTime.Parse("2011-10-27") }
              };
      
              var pc = new PersonComparer();
              var combined = list1.Join(list2, p => p.ID, p => p.ID, (p1,p2) => p2.ChangeDate > p1.ChangeDate ? p2 : p1)
                                  .Union(list1.Except(list2, pc))
                                  .Union(list2.Except(list1, pc));
      
              foreach(var p in combined)
              {
                  Console.WriteLine(p.ID + " " + p.Name + " " + p.ChangeDate);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        您可以将它们连接和排序,然后得到不同的值:

        class PersonIdEqualityComparer : IEqualityComparer<Person>
        {
            public bool Equals(Person x, Person y)
            {
                return x.ID == y.ID;
            }
        
            public int GetHashCode(Person person)
            {
                return person.ID;
            }
        }
        
        var result = list1.Concat(list2)
            .OrderByDescending(i => DateTime.Parse(i.ChangeDate)) // Most recent first
            .Distinct(new PersonIdEqualityComparer())
            ;
        

        这假定Distinct 将从每个集合中取出遇到的第一个项目,而不是任意项目。考虑到它可能只是在遍历集合时将它们插入HashSet,这对我来说似乎是合理的。

        它也没有错误检查。如果任何值可能为 null,或者 ChangeDate 可能无效,则此代码将引发异常。如果这可能是一个问题,我建议您在传递数据之前检查您的数据,并在 PersonIdEqualityComparer 类中进行错误检查。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-04
          • 2020-07-04
          • 2019-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多