2013-06-10 9 views
7

Jaki jest najlepszy sposób napisania struktury kontrolnej, która będzie iterować przez każdą kombinację 2-elementową na liście?Porównywanie każdego elementu ze sobą elementem na liście

Przykład:

{0,1,2} 

chcę mieć blok uruchomić kod trzy razy, raz na każdym z nich:

{0,1} 
{1,2} 
{0,2} 

Próbowałem następujące

foreach (int i in input) 
{ 
    foreach (int j in input.Where(o => o != i)) 
    { 
     //Execute code 
    } 
} 

jednak , to nie zadziała, gdy lista ma dwa takie same elementy. Z

{0,2,0} 

bym nadal chcesz porównać elementy 0 i 0. Wartość nie ma znaczenia.

+1

Co robisz z każdą z tych par? Twoje rozwiązanie i rozwiązania Jona są wszystkie O (n do kwadratu). W zależności od tego, co robisz, może istnieć rozwiązanie O (n). (Na przykład w kompilatorze C# musisz porównać każdą parę metod w rozwiązywaniu problemu z przeciążeniem, aby określić unikalną najlepszą metodę, istnieje algorytm O (n), nawet jeśli relacja lepszej metody jest nieprzechodnia.) –

Odpowiedz

21

Brzmi to może warto coś takiego:

for (int i = 0; i < list.Count - 1; i++) 
{ 
    for (int j = i + 1; j < list.Count; j++) 
    { 
     // Use list[i] and list[j] 
    } 
} 

pewno może to zrobić z LINQ:

var pairs = from i in Enumerable.Range(0, list.Count - 1) 
      from j in Enumerable.Range(i + 1, list.Count - i) 
      select Tuple.Create(list[i], list[j]); 

nie jestem pewien, że to być jaśniejsze chociaż ...

EDYCJA: Kolejna alternatywa, która jest mniej wydajna, ale potencjalnie bardziej przejrzysta:

var pairs = from i in Enumerable.Range(0, list.Count - 1) 
      let x = list[i] 
      from y in list.Skip(i + 1) 
      select Tuple.Create(x, y); 
+0

Idealne, o wiele prostsze niż sobie wyobrażałem. Przyjmuję, kiedy to możliwe. I dziękuję, ale masz rację, rozwiązanie LINQ jest znacznie mniej czytelne i najprawdopodobniej znacznie wolniejsze. – Wilson

Powiązane problemy