我已经看到这个问题已经解决了C#和其他语言,但不适用于Smalltalk。我有3个集合,例如:
a := #(3 4 5).
b := #(4 1 2).
c := #(5 2 3).
我需要做出所有可能的组合,我。 E:
#(3 4 5)
#(3 4 2)
#(3 4 3)
#(3 1 5)
#(3 1 2)
#(3 1 3)
#(3 2 5)
#(3 2 2)
#(3 2 3)
#(4 4 5)
...
我在Squeak和Pharo中看到有组合:atATimeDo:但我不知道如何在这种情况下使用它。这不是功课。有什么帮助吗?
答案 0 :(得分:3)
这有点神秘,但很短暂。它使用块作为匿名函数(有点,它仍然需要从变量中引用,以便可以递归调用它)。
| expand |
expand := [ :prefix :lists |
lists isEmpty
ifTrue: [ Array with: prefix ]
ifFalse: [ | tail |
tail := lists allButFirst: 1.
lists first inject: #() into: [ :all :each |
all, (expand value: (prefix copyWith: each) value: tail) ] ] ].
expand value: #() value: #((3 4 5)(4 1 2)(5 2 3))
答案 1 :(得分:2)
这是Smalltalk / X类库(在SequentialCollection中)的代码。 请参阅示例 - 最后使用注释。
combinationsDo: aBlock
"Repeatly evaluate aBlock with all combinations of elements from the receivers elements.
The receivers elements must be collections of the individuals to be taken for the combinations"
self combinationsStartingAt:1 prefix:#() do:aBlock
combinationsStartingAt:anInteger prefix:prefix do:aBlock
"a helper for combinationsDo:"
|loopedElement|
loopedElement := self at:anInteger.
anInteger == self size ifTrue:[
loopedElement do:[:el | aBlock value:(prefix copyWith:el)].
^ self.
].
loopedElement do:[:el |
|newPrefix|
newPrefix := (prefix copyWith:el).
self combinationsStartingAt:anInteger+1 prefix:newPrefix do:aBlock
].
"
(Array
with:($a to:$d)
with:(1 to: 4))
combinationsDo:[:eachCombination | Transcript showCR: eachCombination]
"
"
(Array
with:#(1 2 3 4 5 6 7 8 9)
with:#(A))
combinationsDo:[:eachCombination | Transcript showCR: eachCombination]
"
"
#( (3 4 5)
(4 1 2)
(5 2 3)
) combinationsDo:[:eachCombination | Transcript showCR: eachCombination]
"
答案 2 :(得分:1)
组合的目的:atATimeDo:用于计算给定大小的分区 要获得笛卡尔积,Martin Kobetic提供的递归函数版本是最短的代码 这是一个迭代变体:
| arrayOfArray n p cartesianProduct |
arrayOfArray := #(
#(3 4 5)
#(4 1 2)
#(5 2 3)
).
n := arrayOfArray size.
p := arrayOfArray inject: 1 into: [:product :array | product * array size].
cartesianProduct := (Array new: p) collect: [:i | Array new: n].
1 to: p do:
[:iSol |
| packetIndex |
packetIndex := iSol - 1.
n to: 1 by: -1 do:
[:iVar |
| ni valuesOfIVar |
ni := (valuesOfIVar := arrayOfArray at: iVar) size.
(cartesianProduct at: iSol)
at: iVar put: (valuesOfIVar at: packetIndex \\ ni + 1).
packetIndex := packetIndex // ni]].
^cartesianProduct