将一个列表的元素分布在另一个列表的元素之上

Distribute elements of one list over elements of another list

我有两个列表:

l1:`a`b`c;
l2: til 20;

我正在尝试创建一个字典 'd',其中包含 'l1' 的元素作为键,'l2' 的元素均匀分布在其中。所以像这样:

d:(`a`b`c)!(0j, 3j, 6j, 9j, 12j, 15j, 18j;1j, 4j, 7j, 10j, 13j, 16j, 19j;2j, 5j, 8j, 11j, 14j, 17j)

元素的顺序无关紧要,我只需要它们平衡即可。我能够以迭代的方式实现这一点(很高兴添加代码,如果这被认为有帮助的话),但必须有一种更优雅的方式(可能使用副词?)。

可以使用 group :

q)group (count[l2]#l1)
(`a`b`c)!(0j, 3j, 6j, 9j, 12j, 15j, 18j;1j, 4j, 7j, 10j, 13j, 16j, 19j;2j, 5j, 8j, 11j, 14j, 17j)

如果您的 l2 是其他东西而不是 til 20 ,那么您必须在分组后重新查找项目:

q)l2: 20#.Q.a
q)l2
"abcdefghijklmnopqrst"
q)l2 group (count[l2]#l1)     // lookup the items back from l2 after grouping 
(`a`b`c)!("adgjmps";"behknqt";"cfilor")

您可以使用 take 运算符的整形功能 #。它有两个参数:至少 2 维的 LHS 和要重塑的列表。

例如 (3;4)#til 12 会将列表 0 1 ... 12 重塑为 3 x 4 矩阵

在我们的例子中,l1 中的元素数不必精确地除以 l2 中的元素数(我们不需要矩形矩阵)。相反,我们可以提供一个 null 作为第二个维度,它将负责分配余数。

q) l1!(count[l1];0N)#l2
a| 0 1 2 3 4 5
b| 6 7 8 9 10 11 12
c| 13 14 15 16 17 18 19

此方法对于较大的输入列表执行得非常好。

作为旁注,当使用 .Q.fc 将矢量参数拆分到 n 个从属设备以进行多线程时,kdb 使用 # 运算符将矢量重塑为 n 向量,每个奴隶一个。

q)d:`a`b`c!{a where x = (a:til 20) mod y}'[til 3;3]
q)d
a| 0 3 6 9 12 15 18
b| 1 4 7 10 13 16 19
c| 2 5 8 11 14 17