View mode: basic / threaded / horizontal-split · Log in · Help
September 17, 2012
lockstep alternative for StoppingPolicy.longest
I need to iterate through two arrays and do some special comparisons,
but the arrays are not guaranteed to have the same length. lockstep
doesn't work with the "longest" policy, e.g.:

int[] a = [1, 2];
int[] b = [1, 2, 3];

foreach (aa, bb; lockstep(a, b, StoppingPolicy.longest))  // throws
{
}

What I would like to have is the ability to set a sentinel value when
.empty returns true for one of the arrays, this would enable this
policy to work. For example I could have:

foreach (aa, bb; lockstep(a, b, StoppingPolicy.longest, -1))  // sentinel is -1
{
   // if aa or bb doesn't exist it's set to -1
}

or alternatively aa/bb could be pointers, and the sentinel would
conveniently be null. Is anything like this in Phobos already?
September 17, 2012
Re: lockstep alternative for StoppingPolicy.longest
On 09/17/2012 03:00 PM, Andrej Mitrovic wrote:
> I need to iterate through two arrays and do some special comparisons,
> but the arrays are not guaranteed to have the same length. lockstep
> doesn't work with the "longest" policy, e.g.:
>
> int[] a = [1, 2];
> int[] b = [1, 2, 3];
>
> foreach (aa, bb; lockstep(a, b, StoppingPolicy.longest))  // throws
> {
> }
>
> What I would like to have is the ability to set a sentinel value when
> .empty returns true for one of the arrays, this would enable this
> policy to work. For example I could have:
>
> foreach (aa, bb; lockstep(a, b, StoppingPolicy.longest, -1))  // sentinel is -1
> {
>      // if aa or bb doesn't exist it's set to -1
> }
>
> or alternatively aa/bb could be pointers, and the sentinel would
> conveniently be null. Is anything like this in Phobos already?

I think you actually want .shortest, no? lockstep's cousin zip() and 
until() may help:

import std.stdio;
import std.range;
import std.algorithm;

void main()
{
    int i, j, k, l, m;
    int*[] a = [&i, null, &j];
    int*[] b = [&k, &l, &m];

    foreach (aa, bb;
             zip(StoppingPolicy.shortest, until!(x => x is null)(a), b))
    {
        writefln("%s and %s", aa, bb);
    }
}

Ali
September 17, 2012
Re: lockstep alternative for StoppingPolicy.longest
On 9/18/12, Ali Çehreli <acehreli@yahoo.com> wrote:
> I think you actually want .shortest, no?

No I want to continue iterating as long as one of the ranges is still
not empty. I'm not doing just comparisons, once there's only one range
that's not empty I have to do some special checks on its elements. In
simple terms:

void main()
{
   enum sentinel = -1;

   // imagine 3rd element missing and lockstep replaces it with -1
   int[] arr1 = [2, 4, -1];
   int[] arr2 = [2, 4, 3];

   bool state;
   foreach (aa, bb; lockstep(arr1, arr2))
   {
       if (aa == sentinel)
       {
           if (aa % 2 == 0)
           {
               state = true;
               break;
           }
       }
       else
       if (bb == sentinel)
       {
           if (bb % 2 == 0)
           {
               state = true;
               break;
           }
       }
       else
       {
           if (aa == bb)
           {
               state = true;
               break;
           }
       }

   }
}

That's not the algorithm I'm using and I'm not dealing with integers
but that's just an example. If either range is empty I want to
continue doing some special work on the range that isn't empty,
otherwise I have to do work on both.
September 17, 2012
Re: lockstep alternative for StoppingPolicy.longest
On 9/18/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>     foreach (aa, bb; lockstep(arr1, arr2))
>     {
>         if (aa == sentinel)
>         {
>             if (aa % 2 == 0)

Gah I've messed up the simple example. If aa was a sentinel then it
meant I wouldn't check it at all, I'd try to check 'bb' instead.
September 17, 2012
Re: lockstep alternative for StoppingPolicy.longest
On 09/17/2012 03:51 PM, Andrej Mitrovic wrote:
> On 9/18/12, Ali Çehreli<acehreli@yahoo.com>  wrote:
>> I think you actually want .shortest, no?
>
> No I want to continue iterating as long as one of the ranges is still
> not empty. I'm not doing just comparisons, once there's only one range
> that's not empty I have to do some special checks on its elements. In
> simple terms:
>
> void main()
> {
>      enum sentinel = -1;
>
>      // imagine 3rd element missing and lockstep replaces it with -1
>      int[] arr1 = [2, 4, -1];
>      int[] arr2 = [2, 4, 3];
>
>      bool state;
>      foreach (aa, bb; lockstep(arr1, arr2))
>      {
>          if (aa == sentinel)
>          {
>              if (aa % 2 == 0)
>              {
>                  state = true;
>                  break;
>              }
>          }
>          else
>          if (bb == sentinel)
>          {
>              if (bb % 2 == 0)
>              {
>                  state = true;
>                  break;
>              }
>          }
>          else
>          {
>              if (aa == bb)
>              {
>                  state = true;
>                  break;
>              }
>          }
>
>      }
> }
>
> That's not the algorithm I'm using and I'm not dealing with integers
> but that's just an example. If either range is empty I want to
> continue doing some special work on the range that isn't empty,
> otherwise I have to do work on both.

Then .longest with zip seems to be the way to go. zip() produces the 
.init value for the short range. Luckily, you are not dealing with 
int.init so perhaps your type's sentinel is distinguishable:

    foreach (aa, bb; zip(StoppingPolicy.longest, a, b))
    {
        if (aa == aa.init) {
        }
        // etc.

        writefln("%s and %s", aa, bb);
    }

Ali
September 17, 2012
Re: lockstep alternative for StoppingPolicy.longest
On 9/18/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 9/18/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>>     foreach (aa, bb; lockstep(arr1, arr2))
>>     {
>>         if (aa == sentinel)
>>         {
>>             if (aa % 2 == 0)
>
> Gah I've messed up the simple example. If aa was a sentinel then it
> meant I wouldn't check it at all, I'd try to check 'bb' instead.
>

Here we go: http://dpaste.dzfl.pl/dff850fb

Hardcoded but could be made to work with multiple ranges (+ i have way
too many runtime checks there). For floating-point this might even
work since a sentinel could be NaN, but for ints there's no reasonable
sentinel. We could use pointers instead and use NULL when the range is
empty.
September 17, 2012
Re: lockstep alternative for StoppingPolicy.longest
On 9/18/12, Ali Çehreli <acehreli@yahoo.com> wrote:
> Then .longest with zip seems to be the way to go.

Ah ain't that cool. It looks like it works. What does it use for the
sentinel, Type.init perhaps?
September 17, 2012
Re: lockstep alternative for StoppingPolicy.longest
On 9/18/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 9/18/12, Ali Çehreli <acehreli@yahoo.com> wrote:
>> Then .longest with zip seems to be the way to go.
>
> Ah ain't that cool. It looks like it works. What does it use for the
> sentinel, Type.init perhaps?
>

Yep just tried with floats and returns NaN. Thanks again, Ali! :)
Top | Discussion index | About this forum | D home