Thread overview
Using iteration / method chaining / etc on multi-dimensional arrays
Apr 12, 2018
Chris Katko
Apr 12, 2018
Uknown
Apr 12, 2018
Chris Katko
Apr 12, 2018
Chris Katko
Apr 12, 2018
Chris Katko
Apr 12, 2018
Paul Backus
Apr 12, 2018
Chris Katko
Apr 12, 2018
Ali Çehreli
Apr 12, 2018
Seb
April 12, 2018
I googled but couldn't find any clear solution.

I've got a 2-D array of strings read from a text file I parsed. So it's like

0 1 15 0 0
2 12 1 0 0
...
0 1 0 10 0

They come in with spaces, so I join into an array between them. But then the last ones have a newline \n on the end, which explodes the to! type conversion.

If it was a single array, I could simply do:

string [25] test;

  test.each((ref n) => n.stripRight());

But how do you do that when it's a 2-D array?

I'm looking not just for this case, but the generate case of iterating / applying filters to 2-D arrays.

Thanks.
April 12, 2018
On Thursday, 12 April 2018 at 15:38:34 UTC, Chris Katko wrote:
> I googled but couldn't find any clear solution.
>
> I've got a 2-D array of strings read from a text file I parsed. So it's like
>
> 0 1 15 0 0
> 2 12 1 0 0
> ...
> 0 1 0 10 0
>
> They come in with spaces, so I join into an array between them. But then the last ones have a newline \n on the end, which explodes the to! type conversion.
>
> If it was a single array, I could simply do:
>
> string [25] test;
>
>   test.each((ref n) => n.stripRight());
>
> But how do you do that when it's a 2-D array?
>
> I'm looking not just for this case, but the generate case of iterating / applying filters to 2-D arrays.
>
> Thanks.

I think something like this would work:

test.each((ref s) => s.each((ref n) => n.stripRight()));

Essentially, get each 1D array from the 2D array, and then apply the algorithms on that. There's probably a better way though
April 12, 2018
On Thursday, 12 April 2018 at 15:38:34 UTC, Chris Katko wrote:
> I googled but couldn't find any clear solution.
>
> I've got a 2-D array of strings read from a text file I parsed. So it's like
>
> 0 1 15 0 0
> 2 12 1 0 0
> ...
> 0 1 0 10 0
>
> They come in with spaces, so I join into an array between them. But then the last ones have a newline \n on the end, which explodes the to! type conversion.
>
> If it was a single array, I could simply do:
>
> string [25] test;
>
>   test.each((ref n) => n.stripRight());
>
> But how do you do that when it's a 2-D array?
>
> I'm looking not just for this case, but the generate case of iterating / applying filters to 2-D arrays.
>
> Thanks.

Use mir for multi-dimensional arrays: https://github.com/libmir/mir-algorithm

It used to be part of phobos, but was removed as phobos's release cycle is too stable and dub gives much more flexibility.
April 12, 2018
On Thursday, 12 April 2018 at 15:47:14 UTC, Uknown wrote:
> On Thursday, 12 April 2018 at 15:38:34 UTC, Chris Katko wrote:
>> I googled but couldn't find any clear solution.
>>
>> I've got a 2-D array of strings read from a text file I parsed. So it's like
>>
>> 0 1 15 0 0
>> 2 12 1 0 0
>> ...
>> 0 1 0 10 0
>>
>> They come in with spaces, so I join into an array between them. But then the last ones have a newline \n on the end, which explodes the to! type conversion.
>>
>> If it was a single array, I could simply do:
>>
>> string [25] test;
>>
>>   test.each((ref n) => n.stripRight());
>>
>> But how do you do that when it's a 2-D array?
>>
>> I'm looking not just for this case, but the generate case of iterating / applying filters to 2-D arrays.
>>
>> Thanks.
>
> I think something like this would work:
>
> test.each((ref s) => s.each((ref n) => n.stripRight()));
>
> Essentially, get each 1D array from the 2D array, and then apply the algorithms on that. There's probably a better way though

But each doesn't return anything, it mutates, right? I think that's the problem I ran into with my attempt. With your code, I get an error about void:

  string []x = split(file.readln.idup, " ");
  x.each((ref s) => s.each((ref n) => n.stripRight()));

extra.d(2493): Error: template std.algorithm.iteration.each cannot deduce function from argument types !()(string[], void), candidates are:
/usr/include/dmd/phobos/std/algorithm/iteration.d(864):        std.algorithm.iteration.each(alias pred = "a")

extra.d(2499): Error: template std.algorithm.mutation.stripRight cannot deduce function from argument types !()(string), candidates are:
/usr/include/dmd/phobos/std/algorithm/mutation.d(2363):        std.algorithm.mutation.stripRight(Range, E)(Range range, E element) if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool))
/usr/include/dmd/phobos/std/algorithm/mutation.d(2375):        std.algorithm.mutation.stripRight(alias pred, Range)(Range range) if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))

extra.d(2500): Error: template std.algorithm.mutation.stripRight cannot deduce function from argument types !()(string), candidates are:
/usr/include/dmd/phobos/std/algorithm/mutation.d(2363):        std.algorithm.mutation.stripRight(Range, E)(Range range, E element) if (isBidirectionalRange!Range && is(typeof(range.back == element) : bool))
/usr/include/dmd/phobos/std/algorithm/mutation.d(2375):        std.algorithm.mutation.stripRight(alias pred, Range)(Range range) if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool))
April 12, 2018
Wait, that might not be the error.
April 12, 2018
On Thursday, 12 April 2018 at 20:37:49 UTC, Chris Katko wrote:
> Wait, that might not be the error.

Just the top one. This one:

extra.d(2493): Error: template std.algorithm.iteration.each cannot deduce function from argument types !()(string[], void), candidates are:
/usr/include/dmd/phobos/std/algorithm/iteration.d(864):        std.algorithm.iteration.each(alias pred = "a")

April 12, 2018
On Thursday, 12 April 2018 at 20:34:40 UTC, Chris Katko wrote:
>
> But each doesn't return anything, it mutates, right? I think that's the problem I ran into with my attempt. With your code, I get an error about void:
>
>   string []x = split(file.readln.idup, " ");
>   x.each((ref s) => s.each((ref n) => n.stripRight()));

You need to put an exclamation point after 'each' to pass the function as a template parameter:

    x.each!((ref s) => s.each!((ref n) => n.stripRight()));
April 12, 2018
On Thursday, 12 April 2018 at 21:17:30 UTC, Paul Backus wrote:
> On Thursday, 12 April 2018 at 20:34:40 UTC, Chris Katko wrote:
>>
>> But each doesn't return anything, it mutates, right? I think that's the problem I ran into with my attempt. With your code, I get an error about void:
>>
>>   string []x = split(file.readln.idup, " ");
>>   x.each((ref s) => s.each((ref n) => n.stripRight()));
>
> You need to put an exclamation point after 'each' to pass the function as a template parameter:
>
>     x.each!((ref s) => s.each!((ref n) => n.stripRight()));

DOH.

But now I'm here:

extra.d(2493): Error: template extra.map_t.load_map2.each!((ref s) => s.each!((ref n) => n.stripRight())).each cannot deduce function from argument types !()(string[]), candidates are:

/usr/include/dmd/phobos/std/algorithm/iteration.d(899):        extra.map_t.load_map2.each!((ref s) => s.each!((ref n) => n.stripRight())).each(Range)(Range r) if (!isForeachIterable!Range && (isRangeIterable!Range || __traits(compiles, typeof(r.front).length)))

/usr/include/dmd/phobos/std/algorithm/iteration.d(934):        extra.map_t.load_map2.each!((ref s) => s.each!((ref n) => n.stripRight())).each(Iterable)(auto ref Iterable r) if (isForeachIterable!Iterable || __traits(compiles, Parameters!(Parameters!(r.opApply))))


From:

string []x = split(file.readln.idup, " ");
import std.algorithm;
x.each!((ref s) => s.each!((ref n) => n.stripRight()));

Looks like it can't tell if it's a Range or... an auto ref Iterable?
April 12, 2018
On 04/12/2018 02:22 PM, Chris Katko wrote:
> On Thursday, 12 April 2018 at 21:17:30 UTC, Paul Backus wrote:
>> On Thursday, 12 April 2018 at 20:34:40 UTC, Chris Katko wrote:
>>>
>>> But each doesn't return anything, it mutates, right? I think that's the problem I ran into with my attempt. With your code, I get an error about void:
>>>
>>>   string []x = split(file.readln.idup, " ");
>>>   x.each((ref s) => s.each((ref n) => n.stripRight()));
>>
>> You need to put an exclamation point after 'each' to pass the function as a template parameter:
>>
>>     x.each!((ref s) => s.each!((ref n) => n.stripRight()));
> 
> DOH.
> 
> But now I'm here:
> 
> extra.d(2493): Error: template extra.map_t.load_map2.each!((ref s) => s.each!((ref n) => n.stripRight())).each cannot deduce function from argument types !()(string[]), candidates are:
> 
> /usr/include/dmd/phobos/std/algorithm/iteration.d(899): extra.map_t.load_map2.each!((ref s) => s.each!((ref n) => n.stripRight())).each(Range)(Range r) if (!isForeachIterable!Range && (isRangeIterable!Range || __traits(compiles, typeof(r.front).length)))
> 
> /usr/include/dmd/phobos/std/algorithm/iteration.d(934): extra.map_t.load_map2.each!((ref s) => s.each!((ref n) => n.stripRight())).each(Iterable)(auto ref Iterable r) if (isForeachIterable!Iterable || __traits(compiles, Parameters!(Parameters!(r.opApply))))
> 
> 
> From:
> 
> string []x = split(file.readln.idup, " ");
> import std.algorithm;
> x.each!((ref s) => s.each!((ref n) => n.stripRight()));
> 
> Looks like it can't tell if it's a Range or... an auto ref Iterable?

Assuming the file "2darray" includes

0 1 15 0 0
2 12 1 0 0
0 1 0 10 0

the following program produces a range of ranges that produce the intended integer values:

import std.stdio;
import std.algorithm;
import std.conv;

void main() {
    auto file = File("2darray");
    auto r = file.byLine.map!(l => l.splitter.map!(to!int));
    writefln("%(%s\n%)", r);
}

The output is

[0, 1, 15, 0, 0]
[2, 12, 1, 0, 0]
[0, 1, 0, 10, 0]

If you want to produce an actual 2d array, you can add two .array calls at that chain:

    import std.range : array;
    auto r = file.byLine.map!(l => l.splitter.map!(to!int).array).array;

Ali