如何从 kdb 中的 csv 文件内容构建字典?

How to build a dictionary from contents of a csv file in kdb?

我有一个 csv 文件,内容如下

source,address,table,tableName,sym,symSet
source_one,addr1:port1:id1:pass1,table_one,tableName1,syms_one,SYM1 SYM2 SYM3
source_two,addr2:port2:id2:pass2,table_two,tableName2,syms_two,SYM21 SYM22 SYM23

我将 csv 加载到 table 的代码如下

table:("******";enlist ",") 0: `sourceFileName.csv

我想用 'table' 的内容创建一个字典,格式如下

source_one|addr1:port1:id1:pass1
table_one|tableName1
syms_one|SYM1 SYM2 SYM3
source_two|addr2:port2:id2:pass2
table_two|tableName2
syms_two|SYM21 SYM22 SYM23

如何实现?

谢谢!

一种方法是这样的:

q)(!) . flip raze 2 cut'1_flip("******";",")0:`:test.csv
"source_one"| "addr1:port1:id1:pass1"
"table_one" | "tableName1"
"syms_one"  | "SYM1 SYM2 SYM3"
"source_two"| "addr2:port2:id2:pass2"
"table_two" | "tableName2"
"syms_two"  | "SYM21 SYM22 SYM23"

(如果您希望键和值作为符号,请将 0: 参数中的 * 替换为 S

这是通过以字符串列表的形式读取文件,翻转到原始行,删除第一行(即 headers),对每一行执行 2 cut 来拆分成对,使用 raze 删除嵌套级别,然后最终使用 dot apply! 函数(即制作字典)应用于此翻转,以便左侧参数为 ! 是键,右 arg 是值。

鉴于上面定义的 table,您可以使用 value 从没有列 headers 的 table 中提取数据:

q)value each table
"source_one" "addr1:port1:id1:pass1" "table_one" "tableName1" "syms_one" "SYM1 SYM2 SYM3"
"source_two" "addr2:port2:id2:pass2" "table_two" "tableName2" "syms_two" "SYM21 SYM22 SYM23"

从这里您可以 raze 输出一个列表,然后可以 cut 成对 (2):

q)2 cut raze value each table
"source_one" "addr1:port1:id1:pass1"
"table_one"  "tableName1"
"syms_one"   "SYM1 SYM2 SYM3"
...

最后使用 flip 将其转换为可用于制作字典的格式 !:

(!). flip 2 cut raze value each table
"source_one"| "addr1:port1:id1:pass1"
"table_one" | "tableName1"
"syms_one"  | "SYM1 SYM2 SYM3"
"source_two"| "addr2:port2:id2:pass2"
"table_two" | "tableName2"
"syms_two"  | "SYM21 SYM22 SYM23"

如果键需要是符号那么你可以使用@ apply 在创建字典之前转换它们:

(!). @[;0;`$]flip 2 cut raze value each table

更好的方法可能是在不使用 enlist 的情况下创建 table 并在使用相同方法之前使用 1_ 删除列 headers创建字典:

(!). flip raze cut[2]each 1_flip("******";",") 0: `:source.csv

您也可以使用 0: 直接解析键值对,但这需要更改文本文件的存储方式。

需要删除第一行并在每行末尾添加逗号:

$ cat test.txt
source_one=addr1:port1:id1:pass1,table_one=tableName1,syms_one=SYM1 SYM2 SYM3,
source_two=addr2:port2:id2:pass2,table_two=tableName2,syms_two=SYM21 SYM22 SYM23,

如果改负载容易就变成一根线:

q)(!). "S=,"0: raze  read0 `:test.txt
source_one| "addr1:port1:id1:pass1"
table_one | "tableName1"
syms_one  | "SYM1 SYM2 SYM3"
source_two| "addr2:port2:id2:pass2"
table_two | "tableName2"
syms_two  | "SYM21 SYM22 SYM23"

如果数据不规则,这比加载到 table 有优势,例如,没有一行有源和 table 和符号。 如果他们这样做了,为什么不直接将它们作为 table 中的列名?

我会放弃 table 创作并做这样的事情:

q)(!). flip 2 cut raze ","vs/:1_read0`source.csv
"source_one"| "addr1:port1:id1:pass1"
"table_one" | "tableName1"
"syms_one"  | "SYM1 SYM2 SYM3"
"source_two"| "addr2:port2:id2:pass2"
"table_two" | "tableName2"
"syms_two"  | "SYM21 SYM22 SYM23"

说明。从右到左,首先,1_read0 将源文件作为行列表读取并丢弃第一行。其次,","vs/:"," 分隔符上剪切每一行。第三,2 cut raze 将列表列表展平并成对切割。第四,flip 将成对列表转置为一对列表。最后,(!). 从一对包含键和值的列表构造一个字典。请注意 (!).(x;y) 转换为 x!y.