首页 > 解决方案 > 生成唯一排列列表

问题描述

假设我有 3 个符号的列表:

l:`s1`s2`s3

生成以下 n*(n+1)/2 排列列表的 q 方式是什么?

(`s1;`s1),(`s1;`s2),(`s1;`s3),(`s2;`s2),(`s2;`s3),(`s3;`s3)

这可以看作是在相关矩阵的上下文中,我想要相关矩阵的所有上三角部分,包括对角线。

当然我的初始列表的大小会超过 3,所以我想要一个通用函数来执行这个操作。

我知道如何生成对角线元素:

q) {(x,y)}'[l;l]

(`s1`s1;`s2`s2;`s3`s3)

但我不知道如何生成非对角元素。

标签: permutationkdb

解决方案


您可能会发现另一个有用的解决方案:

q)l
`s1`s2`s3
q){raze x,/:'-1_{1_x}\[x]}l
s1 s1
s1 s2
s1 s3
s2 s2
s2 s3
s3 s3

这使用扫描累加器创建符号列表列表,每个符号列表删除第一个元素:

q)-1_{1_x}\[l]
`s1`s2`s3
`s2`s3
,`s3

需要额外-1_的,因为扫描最后也会返回一个空列表。然后使用 each-right 和 each 将列表的每个元素连接到此结果中:

{x,/:'-1_{1_x}\[x]}l
(`s1`s1;`s1`s2;`s1`s3)
(`s2`s2;`s2`s3)
,`s3`s3

最后使用 raze 来获得不同的排列。

编辑:也可以使用

q){raze x,/:'til[count x]_\:x}l
s1 s1
s1 s2
s1 s3
s2 s2
s2 s3
s3 s3

它根本不需要扫描,并且在性能方面与扫描解决方案非常相似!


推荐阅读