digitalmars.D - Array index slicing
- bearophile (73/73) Jul 13 2012 In my D code I have inserted few times the same bug, that I show
- travert phare.normalesup.org (Christophe Travert) (3/15) Jul 16 2012 enumerate could be useful with retro too. You may want to change the
In my D code I have inserted few times the same bug, that I show
here with a simplified example.
I have to create a matrix like this:
0 10 20 30
0 11 21 31
0 12 22 32
There are many ways to inizialize a matrix like that, this is one
way, but it's not complete:
import std.stdio;
void main() {
auto M = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];
foreach (r, row; M)
foreach (c, ref item; row)
item = c * 10 + r;
writefln("%(%s\n%)", M);
}
It outputs:
[0, 10, 20, 30]
[1, 11, 21, 31]
[2, 12, 22, 32]
To complete the algorithm, that is to not touch the first column,
I can use just a slice in the second foreach, to not touch the
first column:
import std.stdio;
void main() {
auto M = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];
foreach (r, row; M)
foreach (c, ref item; row[1 .. $])
item = c * 10 + r;
writefln("%(%s\n%)", M);
}
But this introduces the bug:
[0, 0, 10, 20]
[0, 1, 11, 21]
[0, 2, 12, 22]
Slicing 'row' from the second item I avoid to write on the first
cells of each row, but the 'c' index doesn't get sliced, it
starts from zero still. One correct version needs to increment c
by one in the formula:
import std.stdio;
void main() {
auto M = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];
foreach (r, row; M)
foreach (c, ref item; row[1 .. $])
item = (c + 1) * 10 + r;
writefln("%(%s\n%)", M);
}
Another solution is to ignore the c==0:
foreach (r, row; M)
foreach (c, ref item; row)
if (c != 0)
item = c * 10 + r;
I don't consider this a D/Phobos bug, but maybe there are library
ways to help me (and others) avoid it.
In this enhancement request I have asked for an enumerate() in
Phobos:
http://d.puremagic.com/issues/show_bug.cgi?id=5550
enumerate() is similar to the Python built-in iterable, it just
yields pairs of (count,item), counting the items of a given
iterable (range).
If enumerate() is well implemented it's one way to avoid that
problem (other solutions are possible), now 'c' gets sliced, so
it doesn't start from zero:
import std.stdio;
void main() {
auto M = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];
foreach (r, row; M)
foreach (c, ref item; enumerate(row)[1 .. $])
item = c * 10 + r;
writefln("%(%s\n%)", M);
}
Bye,
bearophile
Jul 13 2012
"bearophile" , dans le message (digitalmars.D:172300), a écrit :
If enumerate() is well implemented it's one way to avoid that
problem (other solutions are possible), now 'c' gets sliced, so
it doesn't start from zero:
import std.stdio;
void main() {
auto M = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];
foreach (r, row; M)
foreach (c, ref item; enumerate(row)[1 .. $])
item = c * 10 + r;
writefln("%(%s\n%)", M);
}
enumerate could be useful with retro too. You may want to change the
order of the enumeration, but not the order of the indices.
Jul 16 2012








travert phare.normalesup.org (Christophe Travert)