比较两个对象列表以进行同步

时间:2012-09-24 08:37:16

标签: c# c#-4.0

假设我有一个班级,

Class A
{
    ID;
    Name;
    LastModifiedDate;
}

我有两个List,ListA1和ListA2,

ListA1 = new List<A>(); 
ListA2 = new List<A>();

ListA1.Add(new A{ ID=1, Name="A", LastModifiedDate='1/1/2000' })
ListA1.Add(new A{ ID=2, Name="B", LastModifiedDate='1/2/2000' })
ListA1.Add(new A{ ID=3,Name="C", LastModifiedDate='1/2/2000' })
...................................................


ListA2.Add(new A{ ID=4, Name="D", LastModifiedDate='1/4/2000' })
ListA2.Add(new A{ ID=1, Name="A", LastModifiedDate='1/5/2000' })
ListA3.Add(new A{ ID=2, Name="B", LastModifiedDate='1/2/2000' })

现在,我需要通过比较LastModifiedDate来比较ListA1和ListA2。我需要两个新的List,描述ListA1中的新/更新项目以及ListA2中新的/更新的项目。

更新:我看的输出是

newUpadtedListA ={
    new A{ ID=4, Name="D", LastModifiedDate='1/4/2000' },
    new A{ ID=1, Name="A", LastModifiedDate='1/5/2000' }
}

newUpadtedListB ={
    new A{ ID=3, Name="C", LastModifiedDate='1/2/2000' }
}

2 个答案:

答案 0 :(得分:1)

您可以使用Linq和Enumerable.Except:

var a1Modified = ListA1.Select(x => x.LastModifiedDate);
var a2Modified = ListA2.Select(x => x.LastModifiedDate);
var a1NotInA2LastModified = a1Modified.Except(a2Modified);
List<A> newInA1 = (from a1 in ListA1
              join notInA2 in a1NotInA2LastModified
              on a1.LastModifiedDate equals notInA2
              select a1).ToList();

相反,List2中的新内容:

var a2NotInA1LastModified = a2Modified.Except(a1Modified);
List<A> newInA2 = (from a2 in ListA2
              join notInA1 in a2NotInA1LastModified
              on a2.LastModifiedDate equals notInA1
              select a2).ToList();

修改:根据您上一次编辑,ID是唯一的关键列。这应该以一种相当有效的方式为您提供所需的一切:

var a1IDs = ListA1.Select(a => a.ID);
var a2IDs = ListA2.Select(a => a.ID);
var newInA1 = from l1 in ListA1
              join newA1 in a1IDs.Except(a2IDs)
              on l1.ID equals newA1
              select l1;
var newInA2 = from l2 in ListA2
              join newA2 in a2IDs.Except(a1IDs)
              on l2.ID equals newA2
              select l2;
var updatedInA1 = from l1 in ListA1
                  join l2 in ListA2
                  on l1.ID equals l2.ID
                  where l1.LastModifiedDate > l2.LastModifiedDate
                  select l1;
var updatedInA2 = from l2 in ListA2
                  join l1 in ListA1
                  on l2.ID equals l1.ID
                  where l2.LastModifiedDate > l1.LastModifiedDate
                  select l2;

您可以枚举这些序列,并执行添加或更新新/更改项目所需的任何操作。

答案 1 :(得分:1)

  var ListA1 = new AList();
  var ListA2 = new AList();

  ListA1.Add(new A { ID = 1, Name = "A", LastModifiedDate = new DateTime(2012, 01, 01) });
  ListA1.Add(new A { ID = 2, Name = "B", LastModifiedDate = new DateTime(2012, 01, 01) });
  ListA1.Add(new A { ID = 3, Name = "C", LastModifiedDate = new DateTime(2012, 01, 01) });

  ListA2.Add(new A { ID = 4, Name = "D", LastModifiedDate = new DateTime(2012, 01, 02) });
  ListA2.Add(new A { ID = 1, Name = "A", LastModifiedDate = new DateTime(2012, 01, 02) });
  ListA2.Add(new A { ID = 2, Name = "B", LastModifiedDate = new DateTime(2012, 01, 02) });

  ListA1.CompareList(ListA2);

现在我将ListA1与ListA2进行比较,当发生这种情况时,您理论上应该将ListA2中的ID 4添加到ListA1,然后更新ID 1和2,以便输出

ID 1 - 2012/01/02
ID 2 - 2012/01/02
ID 3 - 2012/01/01
ID 4 - 2012/01/02

请将此代码用于输出

  public class AList : List<A>
  {
    public void CompareList(List<A> SecondaryList)
    {
      var compareResults = (from a in SecondaryList
                           join b in this on a.ID equals b.ID into gj
                           from subset in gj.DefaultIfEmpty()
                           select new { IsNew = (subset == null),
                                        IsUpdate = (subset != null && a.LastModifiedDate > subset.LastModifiedDate),
                                        Output = a}).ToList();
      foreach (var compareResult in compareResults)
      {
        if (compareResult.IsNew)
          this.Add(compareResult.Output);
        else if (compareResult.IsUpdate)
          this[this.IndexOf(this.FirstOrDefault(x => x.ID == compareResult.Output.ID))] = compareResult.Output;
      }
    }
  }

编辑:我犯了一个错误,在更新设置中应该是a.LastModifiedDate > subset.LastModifiedDate而不是subset.LastModifiedDate > a.LastModifiedDate,而且循环中也存在一个小问题。

所以我基本上做的是根据ID进行“左连接”。因此ID不加入的地方返回null,但是我们总是希望输出为“辅助列表”,这是因为我们需要更新或编辑然后我们需要使用列表2中的对象。如果有的话null表示它不存在于列表一中,因此我们将IsNew设置为true,如果返回值不为null并且返回结果的修改日期更新,则设置IsUpdate