我正在使用Mathematica 7并使用combinatorica包函数我可以从一个元素列表中得到一定数量的所有组合,其中顺序无关紧要且没有重复.g:
in: KSubsets[{a, b, c, d}, 3]
out: {{a, b, c}, {a, b, d}, {a, c, d}, {b, c, d}}
我找不到一个函数,它会从订单无关紧要且 重复的元素列表中给出一定数量的所有组合。 即,上述示例将在输出中包含{a,a,b},{a,a,a},{b,b,b}等元素。
可能需要自定义功能。如果我能想出一个,我会发一个答案但是现在我没有看到明显的解决方案。
编辑: 理想情况下,输出不包含组合的重复,例如 元组[{a,b,c,d},3] 将返回一个包含两个元素的列表,如{a,a,b}和{b,a,a} 从组合的角度来看是相同的。
答案 0 :(得分:10)
您可以将每个组合编码为{na,nb,nc,nd}
,其中na表示a
出现的次数。然后,任务是找到加起来为3的4个非负整数的所有可能组合。IntegerPartition
提供了一种快速生成所有此类组合的方法,其中顺序无关紧要,并且您使用{{Permutations
跟随它1}}以解释不同的订单
vars = {a, b, c, d};
len = 3;
coef2vars[lst_] :=
Join @@ (MapIndexed[Table[vars[[#2[[1]]]], {#1}] &, lst])
coefs = Permutations /@
IntegerPartitions[len, {Length[vars]}, Range[0, len]];
coef2vars /@ Flatten[coefs, 1]
只是为了好玩,这里有针对此任务的IntegerPartitions和Tuples之间的时序比较,以log-seconds为单位
approach1[numTypes_, len_] :=
Union[Sort /@ Tuples[Range[numTypes], len]];
approach2[numTypes_, len_] :=
Flatten[Permutations /@
IntegerPartitions[len, {numTypes}, Range[0, len]], 1];
plot1 = ListLinePlot[(AbsoluteTiming[approach1[3, #];] // First //
Log) & /@ Range[13], PlotStyle -> Red];
plot2 = ListLinePlot[(AbsoluteTiming[approach2[3, #];] // First //
Log) & /@ Range[13]];
Show[plot1, plot2]
答案 1 :(得分:7)
DeleteDuplicates[Map[Sort, Tuples[{a, b, c, d}, 3]]]
答案 2 :(得分:2)
High Performance Mark给出的优雅方法略有不同:
Select[Tuples[{a, b, c, d}, 3], OrderedQ]
排列稍微多样化(但不是你想要的?)
例如:
Select[Permutations[
Sort@Flatten@ConstantArray[{a, b, c, d}, {3}], {2, 3}], OrderedQ]
给出以下
编辑:
Select[Tuples[Sort@{a, b, d, c}, 3], OrderedQ]
可能更好
编辑-2
当然,也可以使用案例。例如
Cases[Permutations[
Sort@Flatten@ConstantArray[{a, b, d, c}, {3}], {2, 3}], _?OrderedQ]
编辑-3。
如果列表包含重复元素,则这两种方法会有所不同。输出来自 例如,以下(方法2)将包含重复项(可能需要也可能不需要):
Select[Tuples[{a, b, c, d, a}, 3], OrderedQ]
他们可能很容易摆脱:
Union@Select[Tuples[{a, b, c, d, a}, 3], OrderedQ]
以下评估为'True'(从显示到方法2的列表中删除重复元素,并对方法1生成的列表进行排序(高性能标记方法):
lst = RandomInteger[9, 50];
Select[Union@Sort@Tuples[lst, 3], OrderedQ] ==
Sort@DeleteDuplicates[Map[Sort, Tuples[lst, 3]]]
如下所示(从方法2的输出中删除重复项,方法1的排序输出):
lst = RandomInteger[9, 50];
Union@Select[Sort@Tuples[lst, 3], OrderedQ] ==
Sort@DeleteDuplicates[Map[Sort, Tuples[lst, 3]]]
对不起!
答案 3 :(得分:2)
这是一个简单的解决方案,它利用了Mathetmatica的内置函数子集,因此在简单性和性能之间取得了很好的平衡。在[n + k-1]的k子集和[n]的k-组合之间存在简单的双射与重复。此功能可将子集更改为重复组合。
CombWithRep[n_, k_] := #-(Range[k]-1)&/@Subsets[Range[n+k-1],{k}]
所以
CombWithRep[4,2]
产量
{{1,1},{1,2},{1,3},{1,4},{2,2},{2,3},{2,4},{3,3},{3,4},{4,4}}