Thread overview
String joining an array of structs or class instances implementing toString?
Feb 11, 2016
pineapple
Feb 11, 2016
pineapple
Feb 11, 2016
Edwin van Leeuwen
Feb 11, 2016
pineapple
Feb 11, 2016
Edwin van Leeuwen
Feb 11, 2016
Meta
Feb 11, 2016
Ali Çehreli
February 11, 2016
It feels like there should be an out-of-the box way to do this but I haven't been able to find it? Help?

This is the thing that I want to do:

struct example{
    const string str;
    //this(string str){ this.str = str; }
    string toString(){
        return this.str;
    }
}

public void main(){
    import std.stdio;
    import std.string;
    example[] parts = [example("hello"), example("world")];
    writeln(std.string.join(parts, " "));
}

February 11, 2016
Oh pardon the constructor I was playing with as a learning experience and forgot to get rid of.
February 11, 2016
On Thursday, 11 February 2016 at 12:44:15 UTC, pineapple wrote:
> It feels like there should be an out-of-the box way to do this but I haven't been able to find it? Help?
>
> This is the thing that I want to do:
>
> struct example{
>     const string str;
>     //this(string str){ this.str = str; }
>     string toString(){
>         return this.str;
>     }
> }
>
> public void main(){
>     import std.stdio;
>     import std.string;
>     example[] parts = [example("hello"), example("world")];
>     writeln(std.string.join(parts, " "));
> }

I'd do it like this:

import std.algorithm : map;
pars.map!((part) => part.toString) // Turn them to strings
 .join(" ").writeln; // Join them.
February 11, 2016
On Thursday, 11 February 2016 at 12:53:20 UTC, Edwin van Leeuwen wrote:
> I'd do it like this:
>
> import std.algorithm : map;
> pars.map!((part) => part.toString) // Turn them to strings
>  .join(" ").writeln; // Join them.

Thanks! Does the map function iterate without constructing an extra list in-memory?
February 11, 2016
On Thursday, 11 February 2016 at 13:43:49 UTC, pineapple wrote:
> Thanks! Does the map function iterate without constructing an extra list in-memory?

Yes, it is lazy, so it only calls toString when the result is actually used (by the join call).


In case you do need to create an extra list you can use array as follows:

import std.array : array;
auto result = parts.map!((part) => part.toString).array;

The call to array will "force" it to construct an array out of it.


February 11, 2016
On Thursday, 11 February 2016 at 12:53:20 UTC, Edwin van Leeuwen wrote:
> I'd do it like this:
>
> import std.algorithm : map;
> pars.map!((part) => part.toString) // Turn them to strings
>  .join(" ").writeln; // Join them.

You can shorten this by using std.conv.to. Also keep in mind that `join` will allocate, but `std.algorithm.joiner` will not.

Ex.

//No allocations done, not even to!string
pars.map!(to!string).joiner(" ").writeln;
February 11, 2016
On 02/11/2016 04:44 AM, pineapple wrote:
> It feels like there should be an out-of-the box way to do this but I
> haven't been able to find it? Help?
>
> This is the thing that I want to do:
>
> struct example{
>      const string str;
>      //this(string str){ this.str = str; }
>      string toString(){
>          return this.str;
>      }
> }
>
> public void main(){
>      import std.stdio;
>      import std.string;
>      example[] parts = [example("hello"), example("world")];
>      writeln(std.string.join(parts, " "));
> }
>

You can use element format specifiers:

    writeln(format("%(%s %)", parts));

writefln understands that too:

    writefln("%(%s %)", parts);

Ali

[1] http://dlang.org/phobos/std_format.html#.formattedWrite
[2] http://ddili.org/ders/d.en/formatted_output.html#ix_formatted_output.%%28