Thread overview
What should I use for concat string into array in loop?
Feb 13
Marc
Feb 13
Seb
February 12
On Tue, Feb 13, 2018 at 01:58:42AM +0000, Marc via Digitalmars-d-learn wrote:
> appender doesn't support string[] so in such case:

Why not? This seems to work:

	import std.array;
	import std.stdio;
	void main() {
		auto app = appender!(string[]);
		foreach (i; 0 .. 1000) {
			app.put("abc");
		}
		writeln(app.data);
	}


T

-- 
"You are a very disagreeable person." "NO."
February 13
appender doesn't support string[] so in such case:

> string[] output;
> for(...) {
>    if(...) {
>      output ~= str;
>     }
> }

Looking for avoid as many immediate allocations as possible, what should I use?
February 12
On Tuesday, February 13, 2018 01:58:42 Marc via Digitalmars-d-learn wrote:
> appender doesn't support string[] so in such case:
> > string[] output;
> > for(...) {
> >
> >    if(...) {
> >
> >      output ~= str;
> >
> >     }
> >
> > }
>
> Looking for avoid as many immediate allocations as possible, what should I use?

Well, the space allocation for dynamic arrays works the same way that it does with something like vector in C++ or ArrayList in Java. So, it's amortized constant cost. So, using ~= is just fine.

That being said, every time that ~= is called, the runtime has to check whether there's room to append in place or whether it has to reallocate the array. In most cases, if you're appending in a loop, there's going to be room, but the check isn't necessarily as cheap as would be nice. So, as an alternative, there's std.array.Appender/appender, which does some of the checks itself instead of calling the runtime, which speeds it up. So, you may want to use Appender, but ~= is going to work just fine.

There's also the reserve function for reserving a minimum capacity for the array, so if you know roughly how much you're going to need, you can call reserve to tell it to allocate at least that much capacity up front and reduce the number of allocations - even eliminate them if you really do know the required capacity up front, since if the capacity is large enough, the call to reserve will have allocated the necessary memory, and none of the append calls will actually end up allocating.

- Jonathan M Davis

February 12
On Monday, February 12, 2018 17:56:45 H. S. Teoh via Digitalmars-d-learn wrote:
> On Tue, Feb 13, 2018 at 01:58:42AM +0000, Marc via Digitalmars-d-learn
wrote:
> > appender doesn't support string[] so in such case:
> Why not? This seems to work:
>
>   import std.array;
>   import std.stdio;
>   void main() {
>       auto app = appender!(string[]);
>       foreach (i; 0 .. 1000) {
>           app.put("abc");
>       }
>       writeln(app.data);
>   }

LOL. I read his message too quickly and missed that he had problem with appender and told him about appender and some alternatives.

I assume that his problem is that he didn't use parens. If he tried appender!string[], then it's not going to work, because the [] ends up being associated with the result of appender!string instead of being associated with string and the passed to appender.

- Jonathan M Davis

February 13
On Tuesday, 13 February 2018 at 01:56:45 UTC, H. S. Teoh wrote:
> On Tue, Feb 13, 2018 at 01:58:42AM +0000, Marc via Digitalmars-d-learn wrote:
>> appender doesn't support string[] so in such case:
>
> Why not? This seems to work:
>
> 	import std.array;
> 	import std.stdio;
> 	void main() {
> 		auto app = appender!(string[]);
> 		foreach (i; 0 .. 1000) {
> 			app.put("abc");
> 		}
> 		writeln(app.data);
> 	}
>
>
> T

Or simply don't allocate at all:

---
import std.algorithm, std.range, std.stdio;

void main()
{
    "abc".repeat(1000).joiner.writeln;
}
---


https://run.dlang.io/is/ubGZwJ


writeln isn't @nogc atm, but if you want to prove that no allocation happens, fallback to printf:

----
import core.stdc.stdio, std.algorithm, std.range, std.stdio;

void main() @nogc
{
    "abc".repeat(1000).each!(s => printf("%.*s", s.length, s.ptr));
}
---

https://run.dlang.io/is/V7PWXj