2013-04-10 6 views

Odpowiedz

16

Można to zrobić poprzez Enumerable.Zip:

bool sequential = values.Zip(values.Skip(1), (a,b) => (a+1) == b).All(x => x); 

Działa poprzez każdą parę wartości i sprawdzając, czy drugi jest 1 więcej niż w pierwszym, i powrotu wartości logicznych. Jeśli wszystkie pary pasują do kryteriów, wartości są sekwencyjne.


Biorąc pod uwagę, że jest to lista liczb całkowitych, można to zrobić nieco bardziej wydajnie przy użyciu:

bool sequential = values.Skip(1).Select((v,i) => v == (values[i]+1)).All(v => v); 

to będzie działać tylko na sekwencji, które mogą być dostępne przez indeks. Zauważ, że używamy values[i], a nie values[i-1], ponieważ wywołanie Skip skutecznie przesuwa indeksy.

+0

@dtb Dzięki za naprawienie ... –

+0

+1. Myślę, że można to również zrobić za pomocą Aggregate (po prostu zachowaj różnicę), aby uniknąć wielokrotnego powtarzania sekwencji ... Spróbuję napisać to później jako odpowiedź ... –

+0

@AlexeiLevenkov Moja druga opcja tylko iteruje raz, ale bazuje na sekwencja będąca listą. Mogę zobaczyć, jak to zrobić za pomocą 'Aggregate', ale tylko jeśli sprawisz, że twoja lambda będzie miała nieprzyjemne efekty uboczne ... :( –

10
bool isSequential = Enumerable.Range(values.Min(), values.Count()) 
           .SequenceEqual(values); 
+0

Nie wiem, dlaczego nie została wybrana jako odpowiedź: jest genialnie prosta – user1830285

2

Jedną z opcji jest użycie Aggregate do powtórzenia sekwencji tylko jeden raz.

Należy zauważyć, że w przeciwieństwie do All sugerowanej przez Reed Copsey Aggregate nie może zatrzymać się w środku, gdy warunek nie ...

var s = new int[] {3,4,5,6}.ToList(); 

var isSequential = s.Aggregate 
    (
     new {PrevValue = 0, isFirst = true, Success = true} , 
     (acc, current) => 
      new { 
        PrevValue = current, 
        isFirst = false, 
        Success = acc.Success && (acc.isFirst || (acc.PrevValue == current - 1)) 
       } 
) 
    .Success; 

hodowców wersja byłoby mieć iterator, który niesie poprzednią wartość wzdłuż lub specjalny kod, które Podziel iterator na "First and reszta", pozwalając na implementację rozwiązania Reeda z pojedynczą iteracją dla dowolnego przelicznika.

+0

Dodano "ToList()", ponieważ pytanie dotyczyło listy, chcę kontynuować zabawę i Wersje hodowcy! –

+1

+1 To działa - ale powoduje masę pamięci dla dużych list i nie może zwodzić na sukcesie ... Wciąż wolę jedną z moich opcji (moja druga, w szczególności, jest bardziej wydajna, jeśli wiem, że jest to lista ). –

-1

Jeśli już wiesz, że numery masz w swojej liście jest wyjątkowy, a także klasyfikowane, to najprostsza czek na sekwencyjnym tylko

lst[lst.Count - 1] - lst[0] == lst.Count - 1 

Załóżmy conajmniej 1 element listy.

Powiązane problemy