best way to convert string array of floats to a float array
Jonathan M Davis
jmdavisProg at gmx.com
Tue Jul 24 21:33:20 PDT 2012
On Wednesday, July 25, 2012 06:18:13 Stephen Jones wrote:
> Thanks Jonathan. Very cool language this:
>
> float[] dat;
> dat~=array(map!(to!(float))(split(chompPrefix(s, "lno:"))));
>
> The data is read from a string that contains floats, parsed by
> the split into an array, converted into an array of auto via the
> mapping with the to!float function, and then cast into the float
> array dat.
>
> Longhand that data would be read into the program as a string,
> converted into an array of strings then converted into an array
> of floats and the initial string and the array of strings would
> both accumulate on the GC waiting list. Does the code above weed
> out some of the redundant data thereby reducing calls upon the GC?
I'm not quite sure what you mean. Are you asking whether it tries to avoid
unnecessary copies? It's pretty straightforward in what it does, but there
_is_ some copying going on here.
chompPrefix slices s, so there's no copying.
split _does_ copy, since it returns a new array. Use std.algorithm.splitter if
you want to avoid that copy.
to!float is going to create a float on the stack, so there's no heap alloction.
map is just a wrapper struct which sits on the stack. So, there's no copying
going on there.
array is going to copy the data from map and allocate a new array, which is
then appended to dat, which may or may not cause dat to be reallocated,
depending on whether there are any slices after it or whatnot. In this
particular case, it wouldn't have to, beacause dat is null, but you might as
well assign it directly given the code that you give. If you're appending it
to an array with actual data, then it depends on the state of that array as to
whether reallocation is necessary. If you _really_ want to avoid reallocation
in that case, then you'd do something more like
auto result = map!(to!float)(splitter(chompPrefix(s, "lno:")));
auto dat.reserve(walkLength(result));
foreach(e; result)
dat ~= e;
though that would mean iterating over map twice, since map won't have length
in this case (since splitter doesn't), which could actually result in worse
performance, depending. But it does make it so that the only heap allocation
that you might get is when calling reserve, and if dat happens to have a large
enough capacity already, then there should be zero heap allocations here.
In most cases though, the single line is probably fine (especially if you
change it to use splitter instead of split). I'd only do the second if I were
really trying to eek all the performance out of it that I could.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list