And that's one of the reasons why I like functional programming... Firstly, you
don't really need a new seq for the job you're doing. Your should utilize
iterating over sections separated by ',' but you can modify them in-place (or
even better --- directly write them to the file!).
Here is a little benchmark (100 iterations) for a considerable file (23 KB)
with very few (9) very short (50-60 B for a line) columns:
* Python: 2.08 s
* org Nim: 1.44 s
* KevinGolding's Nim: 1.97 s
* my Nim version: 0.33 s
Here is the code:
import os, strutils
proc main() =
var
pageSize: int = 4096
input = open(paramStr(1), fmRead, pageSize)
output = open(paramStr(4), fmWrite, pageSize)
changeAt = 0
let
toChange = $paramStr 2
changeWith = $paramStr 3
var row = input.readLine()
output.writeLine(row)
block:
var
prev = 0
last = -1
for i in 0 .. row.len-1:
prev = last
last = row.find(',', start=last+1)
if row[prev+1..last-1] == toChange:
changeAt = i
break
while input.readLine(row): # note: the string buffer is reused
var
prev = 0
last = -1
for i in 0 .. changeAt:
prev = last
last = row.find(',', start=last+1) # note: no slicing, just indexing
output.writeLine(row[0..prev], changeWith, row[last..row.len]) # note:
single writeLine
main()
Of course one can make it simpler. What's more... it doesn's seem slower at
all. The only thing I miss here is Rust's "pattern-letting" so I could utilize
a structure instead of a tuple... Nevertheless, here it comes:
import os, strutils
iterator sections(input: string, sep: char = ','): (int,int,int) =
var
prev = 0
last = -1
i = -1
while true:
inc i
prev = last
last = input.find(sep, start=last+1)
yield (i, prev+1, last-1)
if last == -1:
break
proc section(input: string, nr: int, sep: char = ','): (int,int) =
var
prev = 0
last = -1
for i in 0..nr:
prev = last
last = input.find(sep, start=last+1)
result = (prev+1, last-1)
proc findSection(input, name: string, sep: char = ','): (int,int,int) =
for i,lb,hb in input.sections():
if input[lb..hb] == name:
return (i,lb,hb)
proc main() =
var
pageSize: int = 4096
input = open(paramStr(1), fmRead, pageSize)
output = open(paramStr(4), fmWrite, pageSize)
let
toChange = $paramStr 2
changeWith = $paramStr 3
var row = input.readLine()
output.writeLine(row)
let changeAt = row.findSection(toChange)[0]
while input.readLine(row):
let (lb, hb) = row.section(changeAt)
output.writeLine(row[0..lb-1], changeWith, row[hb+1..row.len])
main()
Thank you, functional programming!