【问题标题】:How to get a specific number of random elements from a collection in Smalltalk?如何从 Smalltalk 的集合中获取特定数量的随机元素?
【发布时间】:2016-02-26 10:49:14
【问题描述】:

如何优雅地从集合中获取特定数量 (>1) 的不同随机元素?

【问题讨论】:

    标签: random collections smalltalk pharo


    【解决方案1】:

    考虑下面的代码sn-p

    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 至少没有@ 987654326@不同的元素。

    • 无类代码:方法应该转到某个类。

    例如:

     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
    

    评论

    通常情况下,当我们想要不重复地进行采样时,我们也想从集合中删除元素,因为我们随机选择它们。在这些情况下,通常会发生已知集合没有重复的情况。

    【讨论】:

    • 嗯,我喜欢“byo generator”方法,但是如果集合和样本量很大,您可能会在最后等待一段时间,直到生成器最终选择“free”号码。
    • @AmosM.Carpenter 好点。我使用的更接近第二种方法。
    • 对不起,我很挑剔,但你不应该使用#removeIndex: - 它是私有的。改用公共方法#removeAt: 将获得回答已删除元素的额外好处,这意味着您可以摆脱额外的element 临时变量(即只需执行sample add: (aCollection removeAt: index))。这两种“删除”方法都在 OrderedCollection 上,因此这不适用于其他类型的集合。
    • @AmosM.Carpenter 感谢您的评论。我不是 Pharo 程序员,所以我没有意识到 removeIndex: 是私有的。我已根据您的评论修改了方法。是的,该方法仅适用于OrderCollection(对于大多数实际应用来说应该没问题。)
    【解决方案2】:

    这是我认为看起来或多或少不错的东西,但效率并不高:

    yourCollection asSet asOrderedCollection shuffled first: numberOfElements
    

    【讨论】:

    • 非常优雅。我可以看到提高效率的唯一方法(这通常不会成为问题,但有些人会挂断它......)是洗牌 indices 而不是集合(因为索引会更少),然后使用#atAll: 之类的东西从集合中挑选出那些随机索引(如果你想要它们不同,你仍然需要#asSet)。跨度>
    猜你喜欢
    • 2022-01-22
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    相关资源
    最近更新 更多