I am trying to read from a stream of strings and numbers delimited by commas similar to the way I have read from a stream of strings and numbers delimited by spaces.
Example delimited by spaces (which works):
stream = StringToStream["Apple Jack 1 123.456\nOrange Jill 2 456.789\n"];
While[! EndOfFile === (data =
Read[stream, { Word, Word, Number, Number }]),
Print["Fruit:", data[[1]], " Name:", data[[2]],
" Integer:", data[[3]], " Real:", data[[4]]];
]
Results:
Fruit:Apple Name:Jack Integer:1 Real:123.456
Fruit:Orange Name:Jill Integer:2 Real:456.789
Example delimited by commas (which does not work):
stream = StringToStream["Apple,Jack,1,123.456\nOrange,Jill,2,456.789\n"];
While[! EndOfFile === (data =
Read[stream, { Word, Word, Number, Number }]),
Print["Fruit:", data[[1]], " Name:", data[[2]],
" Integer:", data[[3]], " Real:", data[[4]]];
]
Results:
Fruit:Apple,Jack,1,123.456 Name:Orange,Jill,2,456.789 Integer:EndOfFile Real:EndOfFile
It appears that commas are not default separators.
I added WordSeparators -> "," as an option to Read. Note NumberSeparator is not valid option for Read.
stream = StringToStream["Apple,Jack,1,123.456\nOrange,Jill,2,456.789\n"];
While[! EndOfFile === (data =
Read[stream, { Word, Word, Number, Number }, {WordSeparators -> ","}]),
Print["Fruit:", data[[1]], " Name:", data[[2]],
" Integer:", data[[3]], " Real:", data[[4]]];
]
Results:
Read::readn: Invalid real number found when reading from StringToStream[Apple,Jack,1,123.456
Orange,Jill,2,456.789
]. >>
Fruit:Apple Name:Jack Integer:$Failed Real:EndOfFile
Read::readn: Invalid real number found when reading from StringToStream[Apple,Jack,1,123.456
Orange,Jill,2,456.789
]. >>
Fruit:1 Name:123.456 Integer:$Failed Real:EndOfFile
...
Well this works for words, but not for numbers.
I can always do this, but this seems a little overkill:
stream = StringToStream["Apple,Jack,1,123.456\nOrange,Jill,2,456.789\n"];
While[! EndOfFile === (record = Read[stream, Record]),
data = MapAt[ToExpression, StringSplit[record, ","], {{3}, {4}}];
Print["Fruit:", data[[1]], " Name:", data[[2]],
" Integer:", data[[3]], " Real:", data[[4]]];
]
Results:
Fruit:Apple Name:Jack Integer:1 Real:123.456
Fruit:Orange Name:Jill Integer:2 Real:456.789
Is there something thing that I am missing with Read?
Post answer analysis ...
The check was awarded to the answer that best answered the above question as I am not one to change the rules of the game while it is being played. However the question was flawed by an assumption that I made that both the parsing and conversion in Read would be the most efficient.
If one is looking for the most efficient solution, the following are some results from answers presented (timings are in seconds for 10000 iterations):
Implementation | Timing
-------------------------------+---------
question - Read[] with spaces | 0.220325
Matariki - wo/Sequence[] | 0.250499
Matariki - w/Sequence[] | 0.345603
Heike - Word, Word, Word, Word | 0.351137
Heike - Riffle | 0.380684
question - overkill | 0.395058
ToExpressionto turn them into numbers. – Heike Feb 23 '12 at 20:18Word, Word, Number, Numberto useWord, Word, Number, Real? – Matariki Feb 23 '12 at 20:23Wordshows that the comma is not removed until the next token is pulled from the stream, and whileWordwill respect theWordSeparators,Numberdoes not. It insists on whitespace only. It seems clear thatWordSeparatorsis intended as a list of field separators, but it doesn't act that way. – rcollyer Feb 24 '12 at 02:41