2016-11-23 2 views
1

Ich versuche, zwei Listen desselben Typs mit mehreren Eigenschaften dieses Typs zu vergleichen.C# Vergleiche zwei Listen desselben Objekttyps

Zum Beispiel

Ich habe eine Klasse mit dem Namen Einzelheiten

public class Details 
{ 
    public int id; 
    public string symbol; 
    public string code; 
} 

ich unten zwei Listen haben:

List<Details> list1 = new List<Details>(); 
List<Details> list2 = new List<Details>(); 

list1.Add(new Details() { id=1,symbol="ANSI",code="NITE"}); 
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CALGO" }); 
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CANT" }); 
list1.Add(new Details() { id=2,symbol="ANSI",code="NITE"}); 
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CALGO" }); 
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CANT" }); 

list2.Add(new Details() { id = 1, symbol = "ANSI", code = "NITE" }); 
list2.Add(new Details() { id = 1, symbol = "ANSI", code = "CALGO" }); 
list2.Add(new Details() { id = 2, symbol = "ANSI", code = "NITE" }); 

Ich möchte, dass die Daten von List1 nur die gleiche ID hat, Symbol aber anderer Code.

Also, in obigen Szenario wird das Ergebnis wie folgt sein.

Es wäre großartig, wenn dies durch Linq statt foreach erreicht werden kann.

Ich versuchte unten, aber das ist nicht korrekt.

var temp =list1.Where(x=>list2.Any(z=>x.id==z.id && string.Equals(x.symbol,z.symbol) && !string.Equals(x.code,z.code))); 
+0

Verwenden Sie ein Join. Siehe msdn: https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b – jdweng

Antwort

4

Es sieht aus wie Sie brauchen, um zwei Bedingungen zu erfüllen, nicht eine , Um die Ausgabe zu machen: auf id, symbol und code

  • Es muss sein, ein Spiel auf id und symbol und
  • Es darf kein Spiel sein.

Hier ist, wie das direkt mit LINQ zu tun:

var tmp = list1.Where(x=> 
    list2.Any(z=>x.id==z.id && x.symbol==z.symbol) 
&& !list2.Any(z => x.id==z.id && x.symbol==z.symbol && x.code==z.code)); 

Demo.

Eine Alternative basiert auf der Anwendung De Morgan's laws:

var tmp = list1.Where(x=> 
    list2.Any(z=>x.id==z.id && x.symbol==z.symbol) 
&& list2.All(z => x.id!=z.id || x.symbol!=z.symbol || x.code!=z.code)); 

Demo.

0

natürlich können Sie wie Ihr Code vergleichen, aber wenn Sie Ihren Code wollen, sind mehr Struktur können Sie Methode Equals() und Operator überschreiben ==:

public class Details 
{ 
    public int id; 
    public string symbol; 
    public string code; 

    public override bool Equals(System.Object obj) 
    { 
     if (obj == null) { 
      return false; 
     } 

     Details detail = obj as Details; 
     if ((System.Object) detail == null) { 
      return false; 
     } 

     return (id == detail.id) && (symbol == detail.symbol); 
    } 

    public bool Equals(other) { 
     return this.id == other.id && this.symbole == other.symbol; 
    } 

    public override int GetHashCode() { 
     return id^symbol.GetHashCode(); 
    } 
} 

dann können Sie zwei Details Objekt vergleichen direkt.

1

1) würde ich zum ersten Mal außer Kraft setzen Equals (und auch GetHashCode)

public class Details 
{ 
    public int id; 
    public string symbol; 
    public string code; 

    public override int GetHashCode() 
    { 
     return (id + symbol + code).GetHashCode(); 
    } 

    public override bool Equals(object obj) 
    { 
     var other = obj as Details; 
     if (other == null) return false; 

     return id == other.id && symbol == other.symbol && code == other.code; 
    } 
} 

Dann können Sie Linq verwenden, wie

var result = list1.Except(list2).ToList(); 

Es gibt das Ergebnis Sie erwarten ...


2) gleiche Ergebnis kann auch ohne Änderung des Details Objekt und durch die Implementierung eines benutzerdefinierten IEqualityComparer

public class DetailsComparer : IEqualityComparer<Details> 
{ 
    public bool Equals(Details x, Details y) 
    { 
     return x.id == y.id && x.symbol == y.symbol && x.code == y.code; 
    } 

    public int GetHashCode(Details obj) 
    { 
     return (obj.id + obj.symbol + obj.code).GetHashCode(); 
    } 
} 

Dann wird Ihr Linq wäre

var result = list1.Except(list2, new DetailsComparer()).ToList(); 

Diese Wege sind besser als O (n * n erhalten werden) Algorithmen unter Verwendung von und All

-1

Tun Sie dies:

public class DetailsComparer : IEqualityComparer<Details> 
{ 

    public bool Equals(Details x, Details y) 
     => x.id == y.id && x.symbol == y.symbol && x.code == y.code; 

    public int GetHashCode(Details obj) 
     => obj.code.GetHashCode(); 
} 

Und verwenden Wery einfach, diese

var x = list1.Except(list2, new DetailsComparer()); 

Ergebnis x:

1, ANSI, CANT

2, ANSI, CALGO

2, ANSI, CANT