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