import os, strutils, sequtils, sugar
echo "Average= ", xs.foldl(a + b)/float(xs.len)
main()
Here is the list of numbers: eg> cat grad.data ~/nim/tutorial/eg 190 180 170 160 120 100 100 90 eg> _
The program compiles without incidents: eg> nim c -o:awg.x -d:release --nimcache:lixo awg.nim
However, it does not work:
eg> ./awg.x grad.data strutils.nim(1140) parseFloat Error: unhandled exception: invalid float: [ValueError]
I discovered that split leaves an empty string "" in the xs seq
Now, let us modify the program a bit:
eg# cat avg.nim # nim c -d:release -o:avg.x avg.nim import os, strutils, sequtils, sugar
echo "Average= ", xs.foldl(a + b)/float(xs.len)
main()
The only difference between avg.nim and awg.nim is that I replaced .split(Whitespace) with .splitWhitespace. However, the second version works:
eg> ./avg.x grad.data Average= 138.75
The fact is that split(Whitespace) leaves an empty string "" in the sequence, while splitWhitespace does not.
Dear miran.
I tried your suggestion, and I keep having problems. As you can guess, my idea is to parse a comma separated value file, or csv file for short. In practice, csv files are not separated only by commas. You will find people that combine commas with spaces, or use only spaces. On the contrary of what araq says, I never had problems of writing efficient two line programs for such a task in a straightforward way. As previously mentioned, splitWhitespace works. Then I was able to write something inefficient and messy, such as:
import os, strutils, sequtils, sugar
echo "Average= ", xs.foldl(a+b)/float(xs.len)
main()
Another possibility is this:
import os, strutils, sequtils, sugar
proc fil(x:string) : bool = x != ""
echo "Average= ", xs.foldl(a+b)/float(xs.len)
main()
I can also add a new iterator/procedure to the strutils.nim library:
Although they work, all these solutions are convoluted. Well, splitit* is not convoluted, but I can hardly share it with my collaborators, since it is not in the strutils library by default. Here are short examples of files that I would like to parse:
eg> cat csv.data 190, 180, 170, 160, 120, 100,100, 90
eg> cat nums.data 190 45 23 34 89 96 78 97 14 17 54 345 3 42
eg> cat grad.data 190 180 170 160 120 100 100 90
Of course, I started learning Nim three days ago, and I don't have any experience with Python at all. Probably, if I knew Python, I would be able to devise a good solution for Nim. However, my experience is with Common Lisp, where the clawk library allows me to write very efficient Data Munging programs. To make a long story short, could you suggest a concise and efficient solution in Nim?
I honestly don't see an issue with your solution that uses a filter. That's how it would be done in any other language. If you don't want the extra proc definition, you can use the => sugar like you did with map:
import os, strutils, sequtils, sugar
proc main() =
if paramCount() < 1:
quit("Usage: x-sexpr.x 1000")
let
s = readFile(paramStr(1)).split(Whitespace+{','})
xs= s.filter(x => x.len > 0).map(x => parseFloat x)
echo "Average= ", xs.foldl(a + b)/float(xs.len)
main()
As you can guess, my idea is to parse a comma separated value file, or csv file for short. (...) I don't have any experience with Python at all.
I have a lot of experience with Python and this is sincere advise without being snarky: don't try to write your own manual csv parser, use csv module: https://docs.python.org/3/library/csv.html (I've learnt that the hard way. Never again.)
Probably, if I knew Python, I would be able to devise a good solution for Nim.
Translating Python solution I advise above to Nim, you should use parsecsv module: https://nim-lang.github.io/Nim/parsecsv.html
On the contrary of what araq says, I never had problems of writing efficient two line programs for such a task in a straightforward way.
No, what I say is true, here is what Python does:
"a b ".split(" ")
['a', '', '', 'b', '']