www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is there a more elegant way to do this in D?

reply Brad <bjazmoore outlook.com> writes:
I am trying to take an array and convert it to a string.  I know 
that Split will let me easily go the other way.  I searched for 
the converse of Split but have not been able to locate it.  I can 
think of two brute force methods of doing this.  I found an 
answer to something similar in the forum and adapted it - but it 
is so much code for such a simple procedure:

```d
import std;
void main()
{
     auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0];

     string b = to!string(a.map!(to!string)
      .chunks(a.length)
      .map!join);

     string f = b[2..b.length-2];  //needed to strip the first two 
and las two characters
     writeln(f);

}
```

I want to come out of this with a string that looks like this: 
1011101011110

Thanks in advance.
Apr 07
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 4/7/21 8:57 PM, Brad wrote:

  =C2=A0=C2=A0=C2=A0 auto a =3D [1,0,1,1,1,0,1,0,1,1,1,1,0];
 I want to come out of this with a string that looks like this:=20
 1011101011110
Me, me, me, me! :) import std; void main() { auto a =3D [1,0,1,1,1,0,1,0,1,1,1,1,0]; string s =3D format!"%-(%s%)"(a); writeln(s); } Ali
Apr 07
next sibling parent reply Jack <jckj33 gmail.com> writes:
On Thursday, 8 April 2021 at 04:02:26 UTC, Ali Çehreli wrote:
 On 4/7/21 8:57 PM, Brad wrote:

      auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0];
 I want to come out of this with a string that looks like this: 
 1011101011110
Me, me, me, me! :) import std; void main() { auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0]; string s = format!"%-(%s%)"(a); writeln(s); } Ali
What does %-%s% do?
Apr 08
parent Jack <jckj33 gmail.com> writes:
On Thursday, 8 April 2021 at 16:45:14 UTC, Jack wrote:
 On Thursday, 8 April 2021 at 04:02:26 UTC, Ali Çehreli wrote:
 On 4/7/21 8:57 PM, Brad wrote:

      auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0];
 I want to come out of this with a string that looks like 
 this: 1011101011110
Me, me, me, me! :) import std; void main() { auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0]; string s = format!"%-(%s%)"(a); writeln(s); } Ali
What does %-%s% do?
nevermind, someone just asked this too[1] [1]: https://forum.dlang.org/thread/immypqwvbealjqrvbqln forum.dlang.org
Apr 08
prev sibling parent ddcovery <antoniocabreraperez gmail.com> writes:
On Thursday, 8 April 2021 at 04:02:26 UTC, Ali Çehreli wrote:
 On 4/7/21 8:57 PM, Brad wrote:

      auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0];
 I want to come out of this with a string that looks like this: 
 1011101011110
Me, me, me, me! :) import std; void main() { auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0]; string s = format!"%-(%s%)"(a); writeln(s); } Ali
I'm really addict to the new shortened methods syntax import std; void main() => [1,0,1,1,1,0,1,0,1,1,1,0]. format!"%-(%s%)". writeln;
Apr 09
prev sibling next sibling parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 8 April 2021 at 03:57:23 UTC, Brad wrote:
 I am trying to take an array and convert it to a string.  I 
 know that Split will let me easily go the other way.  I 
 searched for the converse of Split but have not been able to 
 locate it.
You need two functions here: 1. `joiner` [1], which lazily joins the elements of a range. 2. `array` [2], which eagerly evaluates a range and returns an array of its elements. The final code looks like this: dchar[] b = a.map!(to!string).joiner.array; You may have noticed that the type of `b` here is `dchar[]`, not `string`. This is due to a feature of D's standard library known as "auto decoding" [3]. To prevent the strings you get from `to!string` from being auto-decoded into ranges of `dchar`, you can use the function `std.utf.byCodeUnit` [4], like this: string b = a.map!(to!string).map!(byCodeUnit).joiner.array; [1] https://phobos.dpldocs.info/std.algorithm.iteration.joiner.1.html [2] https://phobos.dpldocs.info/std.array.array.1.html [3] https://jackstouffer.com/blog/d_auto_decoding_and_you.html [4] https://phobos.dpldocs.info/std.utf.byCodeUnit.html
Apr 07
prev sibling parent reply WebFreak001 <d.forum webfreak.org> writes:
On Thursday, 8 April 2021 at 03:57:23 UTC, Brad wrote:
 I am trying to take an array and convert it to a string.  I 
 know that Split will let me easily go the other way.  I 
 searched for the converse of Split but have not been able to 
 locate it.  I can think of two brute force methods of doing 
 this.  I found an answer to something similar in the forum and 
 adapted it - but it is so much code for such a simple procedure:

 ```d
 import std;
 void main()
 {
     auto a = [1,0,1,1,1,0,1,0,1,1,1,1,0];

     string b = to!string(a.map!(to!string)
      .chunks(a.length)
      .map!join);

     string f = b[2..b.length-2];  //needed to strip the first 
 two and las two characters
     writeln(f);

 }
 ```

 I want to come out of this with a string that looks like this: 
 1011101011110

 Thanks in advance.
```d string to01String(int[] x) safe { auto conv = x.to!(ubyte[]); // allocates new array, so later cast to string is OK conv[] += '0'; // assume all numbers are 0-9, then this gives the correct result return (() trusted => cast(string)conv)(); } ```
Apr 08
parent reply Meta <jared771 gmail.com> writes:
On Thursday, 8 April 2021 at 12:19:29 UTC, WebFreak001 wrote:
 ```d
 string to01String(int[] x)  safe
 {
     auto conv = x.to!(ubyte[]); // allocates new array, so 
 later cast to string is OK
     conv[] += '0'; // assume all numbers are 0-9, then this 
 gives the correct result
     return (()  trusted => cast(string)conv)();
 }
 ```
The trusted lambda can also be replaced with [std.exception.assumeUnique](https://dlang.org/library/std/exception/assume_unique.html).
Apr 08
parent reply Meta <jared771 gmail.com> writes:
On Thursday, 8 April 2021 at 18:01:56 UTC, Meta wrote:
 On Thursday, 8 April 2021 at 12:19:29 UTC, WebFreak001 wrote:
 ```d
 string to01String(int[] x)  safe
 {
     auto conv = x.to!(ubyte[]); // allocates new array, so 
 later cast to string is OK
     conv[] += '0'; // assume all numbers are 0-9, then this 
 gives the correct result
     return (()  trusted => cast(string)conv)();
 }
 ```
The trusted lambda can also be replaced with [std.exception.assumeUnique](https://dlang.org/library/std/exception/assume_unique.html).
Never mind me, assumeUnique is system (or at least it's inferred as system), and anyway, you can't implicitly convert `immutable(ubyte)[]` to `immutable(char)[]`.
Apr 08
next sibling parent reply Alain De Vos <devosalain71 gmail.com> writes:
The ascii code of 0 is 48 so I think you can add everywhere 48 
(but I'm not a specialist)
Apr 08
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Apr 08, 2021 at 08:28:44PM +0000, Alain De Vos via Digitalmars-d-learn
wrote:
 The ascii code of 0 is 48 so I think you can add everywhere 48 (but
 I'm not a specialist)
Why bother with remembering it's 48? Just add '0', like this: int a = [1, 0, 1, 0, 1, ...]; string s = a.map!(i => cast(char)(i + '0')).array; writeln(s); Or better yet, if you just want to output it and don't need to store the array, just use the range directly: int a = [1, 0, 1, 0, 1, ...]; auto r = a.map!(i => cast(char)(i + '0')); writeln(r); T -- People say I'm arrogant, and I'm proud of it.
Apr 08
parent reply Alain De Vos <devosalain71 gmail.com> writes:
I resume in the 4 ways presented,

import std;
void main(){
	auto a=[1,0,1,1,1,0,1,0,1,1,1,0];
	
	string s = format!"%-(%s%)"(a);
	writeln(s);
	
	dchar[12] b = a.map!(to!string).joiner.array;
	writeln(b);
	
	auto conv = a.to!(ubyte[]);
         conv[]+='0';
        writeln(cast(string)conv);

         auto r = a.map!(i => cast(char)(i + '0'));
	writeln(r);
}

Why do the last two ways need "auto" as type ?
Apr 08
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 8 April 2021 at 22:02:47 UTC, Alain De Vos wrote:
 I resume in the 4 ways presented,

 import std;
 void main(){
 	auto a=[1,0,1,1,1,0,1,0,1,1,1,0];
 	
 	string s = format!"%-(%s%)"(a);
 	writeln(s);
 	
 	dchar[12] b = a.map!(to!string).joiner.array;
 	writeln(b);
 	
 	auto conv = a.to!(ubyte[]);
         conv[]+='0';
        writeln(cast(string)conv);

         auto r = a.map!(i => cast(char)(i + '0'));
 	writeln(r);
 }

 Why do the last two ways need "auto" as type ?
just convenient, saves you a few keystrokes.
Apr 08
parent reply Alain De Vos <devosalain71 gmail.com> writes:
So which concrete types do you give for the two auto's.
Apr 08
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 8 April 2021 at 22:27:38 UTC, Alain De Vos wrote:
 So which concrete types do you give for the two auto's.
The first `auto` is the return type of `to!(ubyte[])`--so, it's `ubyte[]`. The second `auto` is the return type of `map`. If you look at the documentation [2], you'll see that it doesn't give a concrete type for the return value; it just says that `map` returns "an input range." That's because the concrete type is a so-called "Voldemort type" [1]--a type whose name is private to the function, and can't be used externally. Why use such a type? Because it gives the authors of `map` the freedom to change the concrete type without breaking code that uses `map`, as long as the type they change it to still supports the input range interface. [1] https://wiki.dlang.org/Voldemort_types [2] https://phobos.dpldocs.info/std.algorithm.iteration.map.map.html
Apr 08
prev sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 8 April 2021 at 22:27:38 UTC, Alain De Vos wrote:
 So which concrete types do you give for the two auto's.
Like Paul said. But if you really wanted to type it out: a is int[], conv is ubyte[] and the map is lazy, so add .array and it evaluates to char[]
Apr 09
prev sibling parent Q. Schroll <qs.il.paperinik gmail.com> writes:
On Thursday, 8 April 2021 at 18:06:25 UTC, Meta wrote:
 On Thursday, 8 April 2021 at 18:01:56 UTC, Meta wrote:
 On Thursday, 8 April 2021 at 12:19:29 UTC, WebFreak001 wrote:
 ```d
 string to01String(int[] x)  safe
 {
     auto conv = x.to!(ubyte[]); // allocates new array, so 
 later cast to string is OK
     conv[] += '0'; // assume all numbers are 0-9, then this 
 gives the correct result
     return (()  trusted => cast(string)conv)();
 }
 ```
The trusted lambda can also be replaced with [std.exception.assumeUnique](https://dlang.org/library/std/exception/assume_unique.html).
Never mind me, assumeUnique is system (or at least it's inferred as system), and anyway, you can't implicitly convert `immutable(ubyte)[]` to `immutable(char)[]`.
It has to be. It's not ` safe` quite obviously.
Apr 11