2016-06-17 9 views
0

Ich habe eine Liste von String-Arrays. Ich möchte Duplikate und leere Strings entfernen, indem ich nur das erste Element des String-Arrays überprüfe. Ich habe einige SO-Posts gesehen, die IEqualityComparer verwenden, um das Entfernen von Duplikaten zu erreichen, indem ganze String-Arrays verglichen werden, was meiner Meinung nach dazu führt, dass es eleganter und potentiell effizienter aussieht. Allerdings habe ich es nicht geschafft, es nur auf das erste Element des String-Arrays zu überprüfen, um unerwünschte zu entfernen, weil IEqualityComparer mich verwirrt. Wie kann ich das eleganter erreichen? Mein aktueller nicht-elegant & nicht-effizienter Arbeitscode:C# Remove Duplicates Only Überprüfung auf das erste Element des String-Arrays

void method(List<string[]> contactAndNumber) 
{ 
    List<string[]> contactAndNumberSanitized = new List<string[]>(); 
    contactAndNumberSanitized.Clear(); 
    bool rem = false; 
    List<int> remList = new List<int>(); 
    for (int i = 0; i < contactAndNumber.Count; i++) 
    { 
     contactAndNumberSanitized.Add(new string[] { contactAndNumber[i][0], contactAndNumber[i][1] }); 
     for (int j = 0; j < contactAndNumberSanitized.Count; j++) 
      if (i != j) 
       if (contactAndNumber[i][0] == contactAndNumberSanitized[j][0]) 
       { 
        rem = true; 
        break; 
       } 
     if (rem || string.IsNullOrEmpty(contactAndNumber[i][0])) 
      remList.Add(i); 
     rem = false; 
    } 
    for (int i = remList.Count - 1; i >= 0; i--) 
     contactAndNumberSanitized.RemoveAt(remList[i]); 
} 

Und das ist der nicht-funktionierenden Code ich nur eine Überprüfung auf String-Array des ersten Element zu implementieren versucht zu tun:

sealed class EqualityComparer: IEqualityComparer<string[]> 
{ 
    public bool Equals(string[] x, string[] y) 
    { 
     if (ReferenceEquals(x[0], y[0])) 
      return true; 

     if (x == null || y == null) 
      return false; 

     return x[0].SequenceEqual(y[0]); 
    } 

    public int GetHashCode(string[] obj) 
    { 
     if (obj == null) 
      return 0; 

     int hash = 17; 

     unchecked 
     { 
      foreach (string s in obj) 
       hash = hash*23 + ((s == null) ? 0 : s.GetHashCode()); 
     } 

     return hash; 
    } 
} 

von dies unter einem Aufruf der Methode:

var result = list.Distinct(new EqualityComparer()); 

Antwort

3

Ihr Code kann erheblich vereinfacht werden:

var input = new List<string[]> { new[] { "a", "b" }, new[] { "a", "c" }, new[] { "c", "d" }}; 
var result = input.GroupBy(l => l.FirstOrDefault()).Select(g => g.First()); 

Dies gibt Ihnen die eindeutigen Arrays, die das erste Element jedes Arrays verwenden, um die Eindeutigkeit zu bestimmen.

Da Sie jedoch das erste Element des Arrays verwenden, um die Eindeutigkeit zu bestimmen, gibt es einen Kantenfall für eine leere Menge, die als { null } betrachtet wird. Je nachdem, wie Sie leere Sätze behandeln wollen, müssen Sie den Code modifizieren, um die Eingabe zu filtern oder die GroupBy

+0

Ich akzeptiere dieses als die Antwort, da es eine Ein-Zeilen-Lösung ist. Kamerad - top Kerl! =) Kann das Entfernen der Arrays mit einem leeren String-Schlüssel auch innerhalb dieser LINQ-Abfrage implementiert werden? –

+1

@BarryGuvenkaya Sicher, Sie würden einen Filter vor der Gruppe hinzufügen. Zum Beispiel: 'input.Where (a =>! String.IsNullOrEmpty (a.FirstOrDefault())) GroupBy (...'. Which würde alle leeren Arrays entfernen und Arrays mit 'null' als erstes (und/oder nur) element – Rob

0

ändern Da Sie mit einer Liste <T> arbeiten, können Sie die RemoveAll Methode verwenden.

Edit: ursprüngliche Antwort funktioniert möglicherweise nicht. Überarbeitet unten.

Edit 2: Eigentlich, wenn Sie alle Duplikate entfernen möchten (ohne das Original zu verlassen), verwenden Sie diese:

var duplicates = data.Where(x => x == null || string.IsNullOrEmpty(x[0]) || data.Where(y => y != null).Count(y => y[0] == x[0]) > 1).ToList(); 
data.RemoveAll(x => duplicates.Contains(x)); 

Aber wenn Sie die letzte in einer Reihe von Duplikaten lassen (zB die letzte "A" in einem Satz von drei "A" s), dann können Sie meine ursprüngliche Antwort verwenden:

data.RemoveAll(x => x == null || string.IsNullOrEmpty(x[0]) || data.Where(y => y != null).Count(y => y[0] == x[0]) > 1); 
+0

Leider hat das bei mir nicht funktioniert, danke für deine schnelle Antwort. –