我在下面有一个字符串列表。这是一个简单的例子,只有 3 个字符串,每个字符串包含一些键和它们对应的值。例如,字符串 1 表示到期年份为 2024,出生年份为 1947,发行年份为 2015,身高为 150 厘米等。
show q4
"eyr:2024 pid:662406624 hcl:#cfa07d byr:1947 iyr:2015 ecl:amb hgt:150cm"
"iyr:2013 byr:1997 hgt:182cm hcl:#ceb3a1 eyr:2027 ecl:gry cid:102 pid:018128"
"hgt:61in iyr:2014 pid:916315544 hcl:#733820 ecl:oth"
在另一个线程中,terrylynch 向我解释说我可以使用内置的 kdb/q 函数将键值对提取为字典 kdb/q: How to apply a string manipulation function to a vector of strings to output a vector of strings?
dict: each["S: "0:] q4
dict[0]
eyr pid hcl byr iyr ecl hgt
"2024" "662406624" "#cfa07d" "1947" "2015" "amb" "150cm"
然后我尝试将其转换为表格。从概念上讲,我知道 kdb/q 表基本上是翻转的字典,我知道表的行基本上只是字典。
t: flip dict
show t
`eyr`pid`hcl`byr`iyr`ecl`hgt `iyr`byr`hgt`hcl`e..
("2024";"662406624";"#cfa07d";"1947";"2015";"amb";"150cm") ("2013";"1997";"18..
show t[0]
`eyr`pid`hcl`byr`iyr`ecl`hgt
`iyr`byr`hgt`hcl`eyr`ecl`cid`pid
`hgt`iyr`pid`hcl`ecl
show t[1]
("2024";"662406624";"#cfa07d";"1947";"2015";"amb";"150cm")
("2013";"1997";"182cm";"#ceb3a1";"2027";"gry";"102";"018128")
("61in";"2014";"916315544";"#733820";"oth")
这里的问题是上表的每一行都有不同的列。我如何让这个表看起来像下面这样,其中表列是所有键的联合,而一行缺少一个键的值,它只显示为空?
show ideal_t
eyr iyr pid cid..
---------------------------..
2024 2015 662406624 0n ..
2027 2013 018128 102..
谢谢!
答案 0 :(得分:2)
如果许多字典共享密钥,这里是性能更高的解决方案,因为 uj 在大型输入列表上的性能不是很好。该解决方案利用了以下事实:符合标准的字典列表(相同顺序的相同键)会自动解释为 kdb 中的表。
通过将具有相同键的 n 个字典组合在一起,我们最终得到 m 个表,其中 m 作为唯一键集的数量在字典上。使用 group 还允许我们跳过登记每个字典。
然后我们可以使用 Terry 建议的 (uj/) 解决方案将这些 m 个不同的表连接在一起,但是它只会运行 m 次而不是 n 次。 uj 还确保添加到每个表的空值类型正确。
然后,我们在索引列表(group 返回)上使用 iasc 恢复原始排序。
{uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
在不同的输入长度上使用这两个函数的一些性能统计数据。 \ts 的输出定义为 here。当不同集的数量较少时,线性缩放
dict:n#dict (taking your input and extending it to n rows - m is always 3)
n = 1000, m = 3
q)\ts (uj/) enlist each (!) ./: dict
27 519472
\ts {uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
1 304480
n = 10000, m = 3
q)\ts {uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
10 3169504
q)\ts (uj/) enlist each (!) ./: dict
1150 6016432
n = 100000, m = 3
q)\ts {uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
72 37308384
n = 1000000, m = 3
q)\ts {uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
504 308049376
在最坏的情况下,每个字典都有一组不同的键,n=m 并且解决方案收敛到 Terry 的答案,其中应用了 uj n 次
dict:flip ((enlist each neg[n]?`3);n#enlist enlist "test")
n=m=100
q)\ts (uj/) enlist each (!) ./: dict
9 308064
q)\ts {uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
8 318064
n=m=1000
q)\ts (uj/) enlist each (!) ./: dict
1803 24594240
q)\ts {uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
1631 24683344
n=m=2000
q)\ts (uj/) enlist each (!) ./: dict
15777 97955584
q)\ts {uj/[x idx] iasc raze idx:value group key each x} (!) ./: dict
16443 98133264
正如 Jason 提到的,您可以提取一组键并从每个字典中提取它们,这将自动变成一个表(如第一段所述),但是当您有不同类型的不同键时,需要小心被带走。
用 d 索引到下面的第一个字典会返回一个整数 null,但第二个字典中的 d 是一个短整数。结果,列将被混合。
/ a dictionary containing an integer, long and float. Missing keys will return integer nulls
q)(`a`b`c!(1i;2j;3f))[`d]
0Ni
/ Two dictionaries, the first containing a and the second d. Both columns end up mixed
q)dict:((`a`b`c;(1i;2j;3f));(`b`c`d;(4j;5f;6h)))
q){(distinct raze x[;0])#/:(!)./:x}dict
a b c d
----------
1i 2 3 0Ni
0N 4 5 6h
uj 会自动考虑这一点,并在调用 .Q.ff 时确保缺失的键值为正确的 null。
答案 1 :(得分:1)
同样,这可能是您原始主题的后续问题!
但是在这里回答:解析每个字段后,您可以使用 (!/)
转换为字典,并使用 enlist
提升为表。那么这只是一个联合加入 uj
每个迭代的问题
q)(uj/)each[enlist(!/)"S: "0:] q4
eyr pid hcl byr iyr ecl hgt cid
--------------------------------------------------------------
"2024" "662406624" "#cfa07d" "1947" "2015" "amb" "150cm" ""
"2027" "018128" "#ceb3a1" "1997" "2013" "gry" "182cm" "102"
"" "916315544" "#733820" "" "2014" "oth" "61in" ""
答案 2 :(得分:0)
您可以通过从每个字典中“获取”必要的键来避免使用联合连接
q)d:{(-10?`1;10?0N 4#.Q.a)}@'til 10000
q){(distinct raze x[;0])#/:(!)./:x}d
e o i j f n l ..
-----------------------------------------------..
"qrst" "abcd" "ijkl" "efgh" "ijkl" "efgh" "ijkl..
"" "ijkl" "" "" "abcd" "uvwx" "" ..
"qrst" "" "uvwx" "" "ijkl" "yz" "" ..
"" "yz" "" "abcd" "uvwx" "qrst" "ijkl..
"" "uvwx" "" "efgh" "yz" "uvwx" "qrst..
..