I've been trying to make a struct for CSV parsing and manipulating. The code was as follows:
struct CSVData(bool HeaderFromFirstLine)
{
char[][] header = [];
char[][][] rest = [];
this(string filename)
{
auto tmp = File(filename).byLine();
if(HeaderFromFirstLine)
{
this.header = CSVData.parseCSV(tmp.front()).array;
tmp.popFront();
}
this.rest = tmp.map!(e => parseCSV(e)).array;
}
static char[][] parseCSV(char[] str)
{
char[][] tmp = split(str, ",");
return tmp;
}
void print()
{
writeln(this.header);
foreach(e; this.text)
writeln(e);
}
}
void main()
{
auto data = CSVData!true("testdata");
data.print();
}
The "testdata" text file looked like this:
10,15,Hello world
stuff,,more stuff
And the output from running it looked like this:
["st", "ff", ",more stuff"]
["stuff", "", "more stuff"]
As you can see, the header
field is not printing correctly. In an attempt to debug, I added several writeln
s to the constructor:
this(string filename)
{
auto tmp = File(filename).byLine();
if(HeaderFromFirstLine)
{
this.header = CSVData.parseCSV(tmp.front()).array;
tmp.popFront();
writeln(this.header);
}
this.text = tmp.map!(e => parseCSV(e)).array;
writeln(this.header);
}
This produced the following output:
["10", "15", "Hello world"]
["st", "ff", ",more stuff"]
["st", "ff", ",more stuff"]
["stuff", "", "more stuff"]
I then tried commenting out the offending line (the one with the map
) and got the expected result:
["10", "15", "Hello world"]
["10", "15", "Hello world"]
["10", "15", "Hello world"]
Finally, I replaced the offending line and called a different function on tmp
:
writeln(tmp.front);
And got the following result:
["10", "15", "Hello world"]
stuff,,more stuff
["st", "ff", ",more stuff"]
["st", "ff", ",more stuff"]
So it appears that observing or modifying tmp
somehow modifies header
, despite not interacting with it in any visible way.
What is the reason for this? I'm guessing it either has to do with the internals of ranges, or that the arrays were messing up somehow, but I'm not sure.
Thanks in advance!