UWSCでCSVファイルをソートする

公式掲示板より

aaa.csvから数値データを取り出して(3列目-4列目)/9列目の計算結果を元にソートをかけたい

気が向いたので、考えてみた。



答え1

LinersさんのヒントにQSORTを使うものがあるので使ってみた。

DIM fid = FOPEN("aaa.csv", F_READ)
CONST COLS = 9
DIM rows = FGET(fid, F_LINECOUNT), r, c

DIM d[rows][COLS], s[1][rows]
FOR r = 1 TO rows
	FOR c = 1 TO COLS
		d[r][c] = FGET(fid, r, c)
	NEXT
	s[0][r] = ROUND((d[r][3] - d[r][4]) / d[r][9], -4)
	s[1][r] = r
NEXT
FCLOSE(fid)

QSORT(s[0], 0, s[1])

DIM fidw = FOPEN("bbb.csv", F_WRITE)
FOR r = 1 TO rows
	FOR c = 1 TO COLS
		FPUT(fidw, d[s[1][r]][c], r, c)
	NEXT
NEXT
FCLOSE(fidw)

この方法でも充分良いと思われる。
質問者さんのスクリプトにも似ているので、理解できると思われる。
強いて難点を挙げると、

  • QSORTはおそらくクイックソートで、安定ソートではない
  • 入力ファイルと出力ファイルと、内部メモリーの三箇所に同じデータがある

答え2

内部メモリーを削減を考えてみる。

DIM fid = FOPEN("aaa.csv", F_READ)
DIM fidw = FOPEN("bbb.csv", F_WRITE)
DIM rows = FGET(fid, F_LINECOUNT), r, c
CONST SEP = ","
CONST COLS = 9

DIM s = SPLIT(EMPTY), i, t, buf
FOR r = 1 TO rows
	t = ROUND((FGET(fid, r, 3) - FGET(fid, r, 4)) / FGET(fid, r, 9), -4)
	c = LENGTH(s) - 1
	FOR i = 0 TO c
		IF VAL(s[i]) > t THEN BREAK
	NEXT
	buf = ""
	IF i > 0 THEN buf = JOIN(SLICE(s, 0, i - 1), SEP)
	IF LENGTH(buf) THEN buf = buf + SEP
	buf = buf + t
	IF i <= c THEN buf = buf + SEP + JOIN(SLICE(s, i, c), SEP)
	s = SPLIT(buf, SEP)
	FPUT(fidw, FGET(fid, r, 1), i + 1, F_INSERT)
	FOR c = 2 TO COLS
		FPUT(fidw, FGET(fid, r, c), i + 1, c)
	NEXT
NEXT
FCLOSE(fidw)
FCLOSE(fid)

ついでに、安定ソートも目指した。

IF VAL(s[i]) > t THEN BREAK

として確保。
JOIN/SLICEがトリックくさい。

答え3

ソートと言えば、SQL

DIM db = CREATEOLEOBJ("ADODB.Connection")
db.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.;Extended Properties=<#DBL>text;HDR=No;FMT=Delimited<#DBL>")
DIM rs = db.Execute("SELECT * FROM aaa.csv ORDER BY ((F3-F4)/F9)")

DIM fidw = FOPEN("bbb.csv", F_WRITE), c, r = 1
WHILE !rs.EOF
	FOR c = 1 TO 9
		FPUT(fidw, rs.Fields[c].Value, r, c)
	NEXT
	r = r + 1
	rs.MoveNext()
WEND
FCLOSE(fidw)

Microsoft.Jet.OLEDBを使用。
Schema.iniを使えば、Microsoft Text Driverでも可能。
ま、Schema.iniを使いたくなかったので。
CSVの内容によっては、変なデータ変換がかかるので、Schema.iniでMicrosoft Text Driverにするのが推奨。
ソートはODBC任せになったので、トリックは消えたが、安定ソートではなくなった模様、、、。
工夫すれば安定ソートにできると思うけど、もう眠い。


いずれも微妙に問題点がありますね。
まー、いずれの方法でも細かくつめればよいのですけどね。