Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Normalizing chains of .Skip() and .Take() calls

I'm trying to normalize arbitrary chains of .Skip() and .Take() calls to a single .Skip() call followed by an optional single .Take() call.

Here are some examples of expected results, but I'm not sure if these are correct:

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

Can anyone confirm these are the correct results to be expected?


Here is the basic algorithm that I derived from the examples:

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

Any idea how I can confirm if this is the correct algorithm?

like image 662
dtb Avatar asked Mar 26 '10 13:03

dtb


1 Answers

This is a perfect scenario for TDD. Given that you have defined your spec above, this should be cake to implement as a series of just a couple of tests.

"Correct" is fairly subjective, but those examples seem sane.

Also, I would normalize out the .Skip(0) calls.

Make sure you define your edge cases clearly. For example,

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

should probably be normalized into a .Take(0)


Edit:

The official definition of skip:

Bypasses a specified number of elements in a sequence and then returns the remaining elements.

And take:

Returns a specified number of contiguous elements from the start of a sequence.

Based on your examples, I think that your test cases are properly following the spec.

like image 139
John Gietzen Avatar answered Oct 20 '22 20:10

John Gietzen