www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - lockstep alternative for StoppingPolicy.longest

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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?
Sep 17 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Sep 17 2012
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/18/12, Ali =C7ehreli <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 =3D -1; // imagine 3rd element missing and lockstep replaces it with -1 int[] arr1 =3D [2, 4, -1]; int[] arr2 =3D [2, 4, 3]; bool state; foreach (aa, bb; lockstep(arr1, arr2)) { if (aa =3D=3D sentinel) { if (aa % 2 =3D=3D 0) { state =3D true; break; } } else if (bb =3D=3D sentinel) { if (bb % 2 =3D=3D 0) { state =3D true; break; } } else { if (aa =3D=3D bb) { state =3D 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.
Sep 17 2012
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Sep 17 2012
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/18/12, Ali =C7ehreli <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?
Sep 17 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 9/18/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:
 On 9/18/12, Ali =C7ehreli <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! :)
Sep 17 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Sep 17 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Sep 17 2012