2010-03-26 11 views
6

Ich versuche, willkürliche Ketten von .Skip() und .Take() Anrufe zu einem einzigen .Skip() Anruf gefolgt von einem optionalen einzigen .Take() Anruf zu normalisieren.Normalisierung Ketten von .Skip() und .Take() Anrufe

Hier sind einige Beispiele von den erwarteten Ergebnissen, aber ich bin mir nicht sicher, ob diese korrekt sind:

.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) 

Kann jemand bestätigen, das sind die richtigen Ergebnisse zu erwarten?


Hier ist der grundlegende Algorithmus, die ich aus den Beispielen abgeleitet:

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

Jede Idee, wie ich bestätigen kann, ob dies der richtige Algorithmus ist?

+0

Aus Neugier, wofür wird das verwendet? –

+0

@NickLarsen: Ich bin ein LINQ-Abfrage-Provider implementieren und müssen Anrufe überspringen und nehmen in einem einzigen Offset/Anzahl Paar. – dtb

+3

Nicht sicher, wie sie sich verhalten, aber nach der vermuteten Logik, die ich glaube, sollten Sie .Skip (5) .Nehmen (7) .Nehmen (3) => .Schwenk (5) .Nehmen (3) (das sind 3 und nicht 4). Du Code scheint auch diesen Wert zu geben, was ich für korrekt halte – rslite

Antwort

4

Dies ist ein perfektes Szenario für TDD. Da Sie Ihre Spezifikation oben definiert haben, sollte dies Kuchen als eine Reihe von nur ein paar Tests zu implementieren.

"Korrekt" ist ziemlich subjektiv, aber diese Beispiele scheinen vernünftig.

Auch würde ich die .Skip(0) Anrufe normalisieren.

Stellen Sie sicher, dass Sie Ihre Kantenfälle klar definieren. Zum Beispiel

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

sollte wahrscheinlich in ein .Take(0)


Bearbeiten normalisiert werden:

Die offizielle Definition von Überspringen:

Umgeht eine festgelegte Anzahl von Elementen in eine Sequenz und gibt dann die restlichen Elemente zurück.

Und nehmen:

Gibt eine angegebene Anzahl von zusammenhängenden Elementen ab dem Anfang einer Sequenz.

Basierend auf Ihren Beispielen, denke ich, dass Ihre Testfälle die Spezifikation korrekt befolgen.

+0

Das Problem ist nicht so sehr meine eigene Spezifikation zu implementieren, sondern die "richtige" Spezifikation zu finden, da ich kein eigenes Abfragerahmenwerk entwickle, sondern mich an LINQ anschließe. Gibt es eine offizielle Dokumentation, wie LINQ Skip/Take-Implementierungen sich verhalten sollten? – dtb

+0

Richtig, die Dokumentation ist nicht wirklich explizit, wie Ketten bewertet werden sollten, aber aus diesen Spezifikationen stimme ich zu, dass meine Testfälle (die ich aus der Intuition abgeleitet habe) vernünftig aussehen. Ich denke, ich muss mehr Testfälle aufstellen, um alle Randfälle zu erfassen und den Algorithmus entsprechend zu aktualisieren. – dtb