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' }
}
source to share
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.
source to share
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.
source to share