Compare two lists of objects to sync

Let's say I have a class,

Class A
{
    ID;
    Name;
    LastModifiedDate;
}

      

and I have two lists, ListA1 and 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' })

      

Now I need to compare ListA1 and ListA2 by comparing LastModifiedDate. I need two new lists describing what are new / updated items in ListA1 and a description of new / updated items in ListA2.

Update : The conclusion I see is that

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' }
}

      

0


source to share


2 answers


You can use Linq and 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();

      

and vice versa, what's new in 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();

      



Edit : as per your latest board, which ID

is the only key column. This should give you everything you need in a fairly efficient way:

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;

      

You can list these sequences and do whatever you need to do to add or update new / changed items.

+1


source


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

      

Now I am comparing ListA1 to ListA2 and when that happens you should in theory want ID 4 from ListA2 to be added to ListA1 and then ID 1 and 2 to be updated, so the output should be

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

      

Please use this code to output



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

      

EDIT: I made a mistake, should have a.LastModifiedDate > subset.LastModifiedDate

instead subset.LastModifiedDate > a.LastModifiedDate

in the update setup, and also had a small problem in the loop.

So, basically I am doing a "left join" based on the ID. So when the identifier is not concatenated it returns null, however we always want the result to be a "secondary list" because if we need to update or edit we need to use objects from list 2. If there is null it means it does not exist in the list, so we set IsNew

to true and IsUpdate

set if the return is not null and the return result has a newer date.

+1


source







All Articles