2016-01-18 13 views
5

eine Liste von structs Mit oder vielleicht ein Array-Liste mit jeweils drei Elemente haben, wieWie Elemente der Liste von Array/structs zu entfernen, die zwei gemeinsame Elemente

12 8 7 
5 1 0 
7 3 2 
10 6 5 
6 2 1 
8 4 3 
6 1 5 
7 2 6 
8 3 7 
9 4 8 
11 7 6 
13 9 8 
11 6 10 
12 7 11 
13 8 12 
14 9 13 

Ich möchte der Elemente loszuwerden, die haben 2 gemeinsame Subitems in der Liste, im Beispiel würde ich mag

5 1 0 
6 2 1 
6 1 5 
7 3 2 
7 2 6 
8 4 3 
8 3 7 has 2 same items as row 7,3,2 
9 4 8 has 2 same items as row 8,4,3 
10 6 5 
11 7 6 
11 6 10 has 2 same items as row 11,7,6 
12 7 11 has 2 same items as row 11,7,10 
12 8 7 
13 8 12 
13 9 8 
14 9 13 has 2 same items as row 13,9,8 

Also mit structs entfernen gehe ich in die Sortierung der Liste von Element A denke, dann Looping und Vergleichen Elemente, in einer Weise, dass, wenn aktuelle Element 2 Werte entsprechen einem anderen Element in der Liste. Ich füge es jedoch nicht zu einer Ergebnisliste hinzu Ich habe fest und weiß nicht, ob es einen besseren Ansatz

struct S 
     { 
      public int A; 
      public int B; 
      public int C;    
     } 

public void test() 
     { 
      List<S> DataItems = new List<S>(); 
      DataItems.Add(new S { A = 1, B = 2, C=3}); 
      DataItems.Add(new S { A = 12, B = 8, C = 7 }); 
      DataItems.Add(new S { A = 5, B = 1, C = 0 }); 
      DataItems.Add(new S { A = 7, B = 3, C = 2 }); 
      DataItems.Add(new S { A = 10, B = 6, C = 5 }); 
      DataItems.Add(new S { A = 6, B = 2, C = 1 }); 
      DataItems.Add(new S { A = 8, B = 4, C = 3 }); 
      DataItems.Add(new S { A = 6, B = 1, C = 5 }); 
      DataItems.Add(new S { A = 7, B = 2, C = 6 }); 
      DataItems.Add(new S { A = 8, B = 3, C = 7 }); 
      DataItems.Add(new S { A = 9, B = 4, C = 8 }); 
      DataItems.Add(new S { A = 11, B = 7, C = 6 }); 
      DataItems.Add(new S { A = 13, B = 9, C = 8 }); 
      DataItems.Add(new S { A = 11, B = 6, C = 10 }); 
      DataItems.Add(new S { A = 12, B = 7, C = 11 }); 
      DataItems.Add(new S { A = 13, B = 8, C = 12 }); 
      DataItems.Add(new S { A = 14, B = 9, C = 13 }); 
      var sortedList = DataItems.OrderBy(x => x.A); 
      List<S> resultList = new List<S>(); 
      for (int i = 0; i < sortedList.Count(); i++) 
      { 
       for (int j = i+1; j < sortedList.Count(); j++) 
       { 
       if (sortedList.ElementAt(i).A == sortedList.ElementAt(j).A || sortedList.ElementAt(i).A == sortedList.ElementAt(j).B || sortedList.ElementAt(i).A == sortedList.ElementAt(j).C)       
       { 
        //ONE HIT, WAIT OTHER 
       } 
       } 
      } 
     } 

Gibt es eine effizientere Art und Weise ist die Liste zu bekommen, ohne mit 2 gleichen Elemente, die Artikel so würde ich, statt hartzucodieren die Lösung?

5 1 0 
6 2 1 
6 1 5 
7 3 2 
7 2 6 
8 4 3 
10 6 5 
11 7 6 
12 8 7 
13 8 12 
13 9 8 
+0

versucht, mit „Parallel.For“ sehen, wenn die Leistungssteigerung ..? – User2012384

+0

Ok, ich verstehe es besser mit dem Schnitt, aber ich sehe immer noch keine '11,7,10' für' 12 7 11' – Plutonix

Antwort

5

Ein Weg, es zu lösen, ist durch struct S im Zwischenverfahren einzuführen:

public struct S { 
    public int A; 
    public int B; 
    public int C; 

    public bool IsSimilarTo(S s) { 
     int similarity = HasElement(A, s) ? 1 : 0; 
     similarity += HasElement(B, s) ? 1 : 0; 
     return similarity >= 2 ? true : HasElement(C, s);   
    } 

    public bool HasElement(int val, S s) { 
     return val == s.A || val == s.B || val == s.C; 
    } 

    public int HasSimilarInList(List<S> list, int index) { 
     if (index == 0) 
      return -1; 
     for (int i = 0; i < index; ++i)//compare with the previous items 
      if (IsSimilarTo(list[i])) 
       return i; 
     return -1; 
    } 
} 

Dann sind Sie es so ohne Bestellung lösen können:

public void test() { 
    List<S> DataItems = new List<S>(); 
    DataItems.Add(new S { A = 1, B = 2, C = 3 }); 
    DataItems.Add(new S { A = 12, B = 8, C = 7 }); 
    DataItems.Add(new S { A = 5, B = 1, C = 0 }); 
    DataItems.Add(new S { A = 7, B = 3, C = 2 }); 
    DataItems.Add(new S { A = 10, B = 6, C = 5 }); 
    DataItems.Add(new S { A = 6, B = 2, C = 1 }); 
    DataItems.Add(new S { A = 8, B = 4, C = 3 }); 
    DataItems.Add(new S { A = 6, B = 1, C = 5 }); 
    DataItems.Add(new S { A = 7, B = 2, C = 6 }); 
    DataItems.Add(new S { A = 8, B = 3, C = 7 }); 
    DataItems.Add(new S { A = 9, B = 4, C = 8 }); 
    DataItems.Add(new S { A = 11, B = 7, C = 6 }); 
    DataItems.Add(new S { A = 13, B = 9, C = 8 }); 
    DataItems.Add(new S { A = 11, B = 6, C = 10 }); 
    DataItems.Add(new S { A = 12, B = 7, C = 11 }); 
    DataItems.Add(new S { A = 13, B = 8, C = 12 }); 
    DataItems.Add(new S { A = 14, B = 9, C = 13 }); 
    int index = 1; //0-th element does not need to be checked 
    while (index < DataItems.Count) { 
     int isSimilarTo = DataItems[index].HasSimilarInList(DataItems, index); 
     if (isSimilarTo == -1) { 
      ++index; 
      continue; 
     } 
     DataItems.RemoveAt(index); 
    } 
} 
+1

Schön und leicht zu lesen Code ... Auch ist es schwer, einen zu empfehlen, da es O (n^2) ist, wo Wörterbuch Lösung in anderer Antwort ist O (n) ... –

+0

Danke für die Ergänzung. Und ja, als ich das gepostet habe, habe ich bemerkt, dass die andere Antwort schneller ist, da sie doppelt sortiert und die Obergrenze von O (n) hat. Es ist von besserer Leistung. – Ian

+0

@Ian Wie würde ich Ihren Code verwenden, damit ich beide S-Strukturen erhalten kann, die deckungsgleich waren, zum Beispiel 'Zeile 7,3,2 und Zeile 8,3,7 '? weil Wie ich verstehe var 'index' enthält den Index der wiederholten Artikel in der Liste, aber wie würden Sie den Artikel verfolgen, der Wiederholung verursacht? – cMinor

8

ein Element gegeben ...

{ A = 1, B = 2, C = 3 } 

Sie haben 3 mögliche Kombinationen, die in einem anderen Elemente wiederholt werden könnten, zum Beispiel

AB, AC & BC which is {1, 2}, {1, 3} & {2, 3} 

Also, was ich tun würde, ist durch die Liste durchlaufen, diese Kombinationen zu einem Wörterbuch mit einem Separator char (niedrigste Nummer zuerst so, wenn B < A dann BA hinzufügen statt AB) hinzuzufügen. So Sie Dictionary-Schlüssel sein könnte ...

"1-2", "1-3", "2-3" 

Nun, wie Sie jedes Element hinzufügen möchten, prüfen Sie, ob der Schlüssel bereits vorhanden ist, wenn es funktioniert, dann können Sie dieses Element ignorieren (nicht hinzufügen, um es in die Ergebnisliste) .

Leistungsmäßig würde dies einmal durch die ganze Liste gehen und das Wörterbuch verwenden, um nach Artikeln mit 2 gemeinsamen Nummern zu suchen.

+1

Klingt wie es ist der schnellste Weg. Randnotiz: Wenn der Code leistungskritisch ist (oder im Allgemeinen mehr als einmal verwendet wird), sollten Sie eine benutzerdefinierte Schlüsselklasse verwenden, die genau 2 Werte enthält (oder Tuple oder nur anonymes 'neues {L: 1, R: 3}' statt "1- 3"). –

Verwandte Themen