RosettaCodeData/Task/CSV-data-manipulation/Forth/csv-data-manipulation.fth

50 lines
1.9 KiB
Forth

\ csvsum.fs Add a new column named SUM that contain sums from rows of CommaSeparatedValues
\ USAGE:
\ gforth-fast csvsum.fs -e "stdout stdin csvsum bye" <input.csv >output.csv
CHAR , CONSTANT SEPARATOR
3 CONSTANT DECIMALS
1E1 DECIMALS S>D D>F F** FCONSTANT FSCALE
: colsum ( ca u -- F: -- sum ;return SUM from CSV-string )
0E0 OVER SWAP BOUNDS
?DO ( a )
I C@ SEPARATOR =
IF ( a )
I TUCK OVER - >FLOAT IF F+ THEN
1+
THEN
LOOP DROP
;
: f>string ( -- ca u F: x -- )
FSCALE F*
F>D TUCK DABS <# DECIMALS 0 DO # LOOP [CHAR] . HOLD #S ROT SIGN #>
;
: rowC!+ ( offs char -- u+1 ;store CHAR at here+OFFS,increment offset )
OVER HERE + C! 1+
;
: row$!+ ( offs ca u -- offs+u ;store STRING at here+OFFS,update offset )
ROT 2DUP + >R HERE + SWAP MOVE R>
;
\ If run program with '-m 4G'option, we have practically 4G to store a row
: csvsum ( fo fi -- ;write into FILEID-OUTPUT processed input from FILEID-INPUT )
2DUP
HERE UNUSED ROT READ-LINE THROW
IF ( fo fi fo u )
HERE SWAP ( fo fi fo ca u )
SEPARATOR rowC!+
s\" SUM" row$!+ ( fo fi fo ca u' )
ROT WRITE-LINE THROW
BEGIN ( fo fi )
2DUP HERE UNUSED ROT READ-LINE THROW
WHILE ( fo fi fo u )
HERE SWAP ( fo fi fo ca u )
SEPARATOR rowC!+
HERE OVER colsum f>string ( fo fi fo ca u ca' u' )
row$!+ ( fo fi fo ca u'+u )
ROT WRITE-LINE THROW
REPEAT
THEN
2DROP 2DROP
;