2016-02-26 53 views

回答

2

这是我觉得看起来或多或少不错的东西,但效率不高,因为它可以:

yourCollection asSet asOrderedCollection shuffled first: numberOfElements 
+0

非常优雅。我可以看到提高效率(通常不会成为问题,但有些人会挂在上面......)的唯一方法就是将_indices_而不是集合(因为索引会更少) ,然后使用类似'#atAll:'的东西来从集合中挑选那些随机化的索引(如果你想要它们,你仍然需要'#asSet' _distinct_)。 –

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 

一些言论

  • 显式生成器:它明确地使用给定的生成器,即,我称之为aGeneratorRandom的实例。出于数学原因,如果您正在为您的应用程序获取样品,则所有这些应该在整个程序中使用相同的生成器。此外,这将为您带来额外的好处:保存并稍后恢复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 

UPDATE

下面是另一种方法:

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

嗯,我喜欢“byo generator”的方法,但是如果收集和样本量很大,那么您可能会等待很长一段时间,直到发生器最终选择一个“空闲”数字。 –

+0

@ AmosM.Carpenter好点。我使用的是更接近第二种方法。 –

+1

对不起,你应该挑剔,但不应该使用'#removeIndex:' - 它意味着是私人的。使用公共方法'#removeAt:'相反可以回答已删除的元素,这意味着您可以摆脱额外的'element'临时变量(即,只需执行'sample add:(aCollection removeAt:index)') 。这两个“删除”方法都在OrderedCollection上,所以这不适用于其他类型的集合。 –

相关问题