Powiedzmy, że mam klasę,

Class A
{
    ID;
    Name;
    LastModifiedDate;
}

I mam dwie listy, ListA1 i 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' })

Teraz muszę porównać ListA1 i ListA2 przez porównanie LastModifiedDate. Potrzebuję dwóch nowych list, opisujących nowe/zaktualizowane pozycje na LiścieA1 i opisujących nowe/zaktualizowane pozycje na LiścieA2.

Aktualizacja: wynik, którego szukam, jest taki,

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
Imran Qadir Baksh - Baloch 24 wrzesień 2012, 12:37

2 odpowiedzi

Najlepsza odpowiedź

Możesz użyć Linq i 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();

I odwrotnie, co nowego w 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();

Edytuj: zgodnie z ostatnią edycją ID jest jedyną kluczową kolumną. To powinno dać ci wszystko, czego potrzebujesz w dość wydajny sposób:

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;

Możesz wyliczyć te sekwencje i zrobić wszystko, co musisz, aby dodać lub zaktualizować nowe/zmienione elementy.

1
Tim Schmelter 24 wrzesień 2012, 13:28
  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);

Teraz porównuję ListA1 z ListA2 i kiedy tak się stanie, teoretycznie powinieneś chcieć, aby ID 4 z ListA2 został dodany do ListA1, a następnie ID 1 i 2 zostały zaktualizowane, aby dane wyjściowe były

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

Proszę użyć tego kodu do wyjścia

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

EDYCJA: Popełniłem błąd, powinienem być a.LastModifiedDate > subset.LastModifiedDate zamiast subset.LastModifiedDate > a.LastModifiedDate w ustawieniach aktualizacji, a także wystąpił mały problem w pętli.

Więc zasadniczo robię „lewe sprzężenie” na podstawie identyfikatora. Jeśli więc identyfikator się nie łączy, zwraca null, jednak zawsze chcemy, aby wyjściem była „lista wtórna”, ponieważ jeśli potrzebujemy zaktualizować lub edytować, musimy użyć obiektów z listy 2. Jeśli istnieje null oznacza, że ​​nie istnieje na liście pierwszej, dlatego ustawiamy IsNew na true i IsUpdate jest ustawiane, jeśli zwrot nie jest null, a wynik zwracany ma nowszą datę zmodyfikowaną.

1
LukeHennerley 24 wrzesień 2012, 13:32