chaining splitters

Dave S via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Mar 11 02:29:10 PDT 2015


On Wednesday, 11 March 2015 at 00:00:39 UTC, dnoob wrote:
> Hello,
>
> I am parsing some text and I have the following;
>
> string text = "some very long text";
>
> foreach(line; splitter(text, [13, 10]))
> {
> 	foreach(record; splitter(line, '*'))
> 	{
> 		foreach(field; splitter(record, '='))
> 		{
> 			foreach(value; splitter(field, ','))
> 			{
> 				// do something...
> 			}
> 		}
> 	}
> }
>
> I know there is a better way to do that but I'm a total D noob.
>
> Thanks!

You can use std.algorithm's map to apply some function to all the
items in a range:
---

import std.stdio, std.algorithm;

void main()
{
	string text = "foo*bar=qux\r\nHello*world!\r\nApril,May,June";

	auto lines = splitter(text, "\r\n");
	auto records = map!(a => splitter(a, '*'))(lines).joiner();
	auto fields = map!(a => splitter(a, '='))(records).joiner();
	auto values = map!(a => splitter(a, ','))(fields).joiner();

	foreach (value; values)
	{
		writeln(value);
	}
}

---
This produces the output:

foo
bar
qux
Hello
world!
April
May
June

The joiner() is necessary because when you pass a range of
strings to splitter using map the result is a range of ranges of
strings. joiner() joins these together into one range of strings.
Consider this code, for example:
---

string str = "foo*bar=qux\r\nHello*world!\r\nApril,May,June";

auto lines = splitter(str, [13, 10]);
auto result = map!(a => splitter(a, '*'))(lines);
auto tokens = result.joiner();

---
The contents of result are:

["foo", "bar=qux"]
["Hello", "world!"]
["April,May,June"]

The contents of tokens are:

["foo", "bar=qux", "Hello", "world!", "April,May,June"]

I am not a D expert by any means so there it's possible there is
another way that I am not aware of.


More information about the Digitalmars-d-learn mailing list