2016-01-18 32 views
5

Avere una lista di struct o forse una lista di array ciascuno con 3 elementi, comeCome rimuovere gli elementi della lista di matrice/le strutture che dispongono di 2 elementi comuni

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 

voglio sbarazzarsi di elementi che hanno 2 elementi secondari comuni in lista, nell'esempio vorrei rimuovere

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 

quindi, utilizzando le strutture approccio che sto pensando a ordinare l'elenco per elemento a, quindi looping e confrontando gli elementi, in modo che se elemento corrente ha 2 valori uguali ad altri elementi nella lista Non li aggiungo ad una lista di risultati, comunque Sono rimasto bloccato e non so se ci sia un approccio migliore

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

C'è un modo più efficiente per ottenere la lista senza avere voce con 2 stessi elementi quindi vorrei ottenere, invece di hardcoding la soluzione?

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

provato ad utilizzare "Parallel.For" vedere se l'aumento delle prestazioni ..? – User2012384

+0

Ok, lo capisco meglio con la modifica, ma non vedo ancora un '11,7,10' per' 12 7 11' – Plutonix

risposta

5

Un modo per risolverlo è con l'introduzione di metodi intermedi nella struct S:

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

Poi si può risolvere in questo modo senza ordinare:

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

Codice piacevole e facile da leggere ... Inoltre è difficile raccomandarne uno in quanto è O (n^2) dove la soluzione di dizionario in un'altra risposta è O (n) ... –

+0

Grazie per il complemento. E sì, quando ho postato questo ho notato che l'altra risposta è più veloce in quanto fa doppio ordinamento e ha il limite superiore di O (n). È una prestazione migliore. – Ian

+0

@Ian come utilizzerei il tuo codice in modo da poter ottenere entrambe le strutture S che avevano coincidende, ad esempio 'riga 7,3,2 e riga 8,3,7'? perché come ho capito var 'index' contiene l'indice dell'elemento ripetuto in List, ma come terrò traccia dell'elemento che ha causato la ripetizione? – cMinor

8

Dato un oggetto ...

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

Hai 3 possibili combinazioni che potrebbero essere ripetuti in un altro elemento, per esempio

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

Quindi quello che vorrei fare è iterare attraverso la vostra lista, aggiungere quelle combinazioni a un dizionario con un char separatore (numero più basso prima quindi se B < Un quindi aggiungere BA piuttosto che AB). Così si chiavi del dizionario potrebbe essere ...

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

Ora quando si aggiungono ogni elemento, verificare se la chiave esiste già, se lo fa, allora si può ignorare che la voce (non aggiungerlo all'elenco dei risultati) .

Per quanto riguarda le prestazioni, sarebbe una volta l'intero elenco e si utilizza il dizionario per verificare gli elementi con 2 numeri comuni.

+1

Sembra che sia il modo più veloce. Nota a margine: se il codice è critico per le prestazioni (o generalmente usato più volte), considera l'utilizzo di una classe di chiavi personalizzata che contenga esattamente 2 valori (o usa Tuple o solo anonimo 'new {L: 1, R: 3}' invece "1- 3"). –

Problemi correlati