生成唯一排列的列表

问题描述 投票:3回答:3

说我有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)

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

permutation kdb
3个回答
2
投票

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

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

这使用scan accumulator创建符号列表的列表,每个符号列表都删除第一个元素:

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

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


1
投票

我会尝试下面的代码

{distinct asc each x cross x}`s1`s2`s3

It

  • cross生成所有(s_i,s_j)对
  • [asc each按索引对每一对进行排序,因此`s3`s1成为`s1`s3
  • [distinct删除重复项

不是很简短的最有效的方法。


0
投票

[如果我理解了这个问题(如果我错过了一些东西,表示歉意)。下面应该给您您正在寻找的]

q)test:`s1`s2`s3`s4`s5
q)(til cnt) _' raze (-1+cnt:count test)cut test,'/:test
(`s1`s1;`s2`s1;`s3`s1;`s4`s1;`s5`s1)
(`s2`s2;`s3`s2;`s4`s2;`s5`s2)
(`s3`s3;`s4`s3;`s5`s3)
(`s4`s4;`s5`s4)
,`s5`s5
© www.soinside.com 2019 - 2024. All rights reserved.