On Wed, 16 Feb 2011 14:24:36 -0500, Andrej Mitrovic <andrej.mitrov...@gmail.com> wrote:

The only thing I could come up with is exhausting the entire range to
get the length of a bidirectional range. But that's inefficient.
Anyway here's the dull thing:

import std.stdio;
import std.range;
import std.array;

R findBack(alias pred = "a == b", R, E)(R haystack, E needle)
    if (isBidirectionalRange!R)
{
    size_t index;
    bool found;
    auto saved = haystack;

    foreach (item; retro(haystack))
    {
        if (item == needle)
        {
            found = true;
            index++;
            break;
        }
        index++;
    }

    if (found)
    {
        size_t newIndex;
        while (!haystack.empty)
        {
            newIndex++;
            haystack.popBack;
        }

        newIndex -= index;
        while (!saved.empty && newIndex)
        {
            saved.popFront;
            newIndex--;
        }
    }

    return saved;
}

void main()
{
    auto orig = [4, 0, 4, 0];
    auto result = findBack(orig, 4);

    assert(array(result) == [4, 0]);

    result.front = 10;
    assert(orig == [4, 0, 10, 0]);
}

You'll have to forgive me but I have yet to study algorithms properly. :)

Hehe if you are willing to traverse the whole range, it's much easier than this:

auto saved = R.init;
while(!haystack.empty)
{
   if(haystack.front == needle)
      saved = haystack.save();
   haystack.popFront();
}

return saved;

The point is, no matter what you do, the missing ability to construct a range from two iterators/cursors means you must degrade performance to get the desired effect.

This might be able to be simulated with having a range "flip" itself based on certain criteria, but it must be a range-supported feature, which means more complexity goes into the range concept.

-Steve

Reply via email to