Using iteration / method chaining / etc on multi-dimensional arrays

Ali Çehreli acehreli at yahoo.com
Thu Apr 12 21:44:54 UTC 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


More information about the Digitalmars-d-learn mailing list