如何从集合中优雅地获取特定数量(> 1)的不同随机元素?
答案 0 :(得分:5)
请考虑以下代码段
sample: anInteger from: aCollection using: aGenerator
| sample |
sample := Set new: anInteger.
[sample size = anInteger]
whileFalse: [ | element |
element := aCollection atRandom: aGenerator.
sample add: element].
^sample asArray
一些评论
显式生成器:它明确使用给定的生成器,即Random
的实例,我称之为aGenerator
。出于数学原因,如果您要为您的应用程序获取样本,则所有这些样本都应该在您的程序中使用相同的生成器。此外,这将为您提供额外的优势:保存并稍后恢复seed
,您将能够重现系统之前的“随机”行为,这有利于测试。
不检查可用性:代码不会检查是否可以获取所需的样本,如果aCollection
没有,则会出现这种情况。至少anInteger
个不同的元素。
无类别代码:该方法应该转到某个类。
例如:
Random >> sample: anInteger from: aCollection
| sample |
sample := Set new: anInteger.
[sample size = anInteger]
whileFalse: [ | element |
element := aCollection atRandom: self.
sample add: element].
^sample asArray
<强>更新强>
这是另一种方法:
Random >> remove: anInteger from: aCollection
| sample |
sample := OrderedCollection new: anInteger.
anInteger timesRepeat: [| index element |
index := aCollection size atRandom: self.
element := aCollection removeAt: index.
sample add: element].
^sample
<强>注释强>
通常情况下,当我们想要不经重复地进行采样时,我们也希望在随机选择它们时从集合中删除元素。在这些情况下,经常发生的是已知该集合没有重复。
答案 1 :(得分:2)
我认为这看起来或多或少看起来不错,但效率不高:
yourCollection asSet asOrderedCollection shuffled first: numberOfElements