2010-03-26 16 views
6

sto cercando di normalizzare catene arbitrarie di .Skip() e .Take() chiamate a una singola chiamata .Skip() seguita eventualmente da un singolo .Take() chiamata.catene Normalizzazione di .Skip() e .Prendere() chiama

Ecco alcuni esempi di risultati attesi, ma non sono sicuro se questi sono corretti:

.Skip(5)      => .Skip(5) 
.Take(7)      => .Skip(0).Take(7) 

.Skip(5).Skip(7)    => .Skip(12) 
.Skip(5).Take(7)    => .Skip(5).Take(7) 
.Take(7).Skip(5)    => .Skip(5).Take(2) 
.Take(5).Take(7)    => .Skip(0).Take(5) 

.Skip(5).Skip(7).Skip(11)  => .Skip(23) 
.Skip(5).Skip(7).Take(11)  => .Skip(12).Take(11) 
.Skip(5).Take(7).Skip(3)  => .Skip(8).Take(4) 
.Skip(5).Take(7).Take(3)  => .Skip(5).Take(4) 
.Take(11).Skip(5).Skip(3)  => .Skip(8).Take(3) 
.Take(11).Skip(5).Take(7)  => .Skip(5).Take(6) 
.Take(11).Take(5).Skip(3)  => .Skip(3).Take(2) 
.Take(11).Take(5).Take(3)  => .Skip(0).Take(3) 

Qualcuno può confermare questi sono i risultati corretti che si possono attendere?


Ecco l'algoritmo di base che ho derivato dagli esempi:

class Foo 
{ 
    private int skip; 
    private int? take; 

    public Foo Skip(int value) 
    { 
     if (value < 0) 
      value = 0; 

     this.skip += value; 

     if (this.take.HasValue) 
      this.take -= value; 

     return this; 
    } 

    public Foo Take(int value) 
    { 
     if (value < 0) 
      value = 0; 

     if (!this.take.HasValue || value < this.take) 
      this.take = value; 

     return this; 
    } 
} 

Qualsiasi idea di come posso confermare se questo è l'algoritmo corretto?

+0

Per curiosità, a cosa serve? –

+0

@NickLarsen: sto implementando un provider di query LINQ e devo trasformare Skip and Take in una singola coppia offset/conto. – dtb

+3

Non sai come si comportano, ma seguendo la logica presunta credo che dovresti avere .Skip (5) .Take (7) .Take (3) => .Skip (5) .Take (3) (che è prendere 3 e non 4). Il codice sembra dare questo valore, che ritengo sia corretto – rslite

risposta

4

Questo è uno scenario perfetto per TDD. Dato che hai definito le tue specifiche sopra, questo dovrebbe essere cake da implementare come una serie di solo un paio di test.

"Corretto" è abbastanza soggettivo, ma gli esempi sembrano sani.

Inoltre, normalizzerei le chiamate .Skip(0).

Assicurati di definire chiaramente i casi dei bordi. Ad esempio,

.Take(11).Skip(12).Take(1) 

dovrebbe probabilmente essere normalizzato in un .Take(0)


Edit:

La definizione ufficiale di salto:

bypassa un numero specificato di elementi in una sequenza e quindi restituisce gli elementi rimanenti.

e adotta:

Restituisce un numero specificato di elementi contigui dall'inizio di una sequenza.

Sulla base dei vostri esempi, penso che i vostri casi di test seguano correttamente le specifiche.

+0

Il problema non è tanto l'implementazione delle mie specifiche, quanto il trovare la specifica "corretta", dal momento che non sto sviluppando il mio framework di query ma collego LINQ. Esiste qualche documentazione ufficiale su come si comportano le implementazioni Skip/Take di LINQ? – dtb

+0

Giusto, la documentazione non è veramente esplicita su come le catene dovrebbero essere valutate, ma da quelle specifiche sono d'accordo che i miei casi di test (che ho ricavato dall'intuizione) sembrano equilibrati. Credo che dovrò inventare più casi di test per cogliere tutti i casi limite e aggiornare di conseguenza l'algoritmo. – dtb