【问题标题】:Get Random Element(s) from a List从列表中获取随机元素
【发布时间】:2015-09-22 02:39:40
【问题描述】:

我基本上是在寻找相当于 Ruby 的 Array#sample 的 Elixir。可以让我这样做的东西:

list = [1,2,3,4,5,6,7]

sample(list)
#=> 4

sample(list, 3)
#=> [6, 2, 5]

我也没有在Elixir List Docs 中找到任何内容。

【问题讨论】:

  • 我明白你在问什么,但我很好奇为什么这样的函数会成为标准 Ruby 库的一部分。

标签: elixir


【解决方案1】:

更新答案

正如 José Valim 在his answerElixir 1.1 及更高版本中所说,您现在可以使用这些方法从列表中获取随机元素:

示例:

Enum.random(list)                         #=> 4

Enum.take_random(list, 3)                 #=> [3, 9, 1]
Enum.take_random(list, 1)                 #=> [7]

记得先拨打:random.seed(:erlang.now)


原答案

我仍然找不到“正确”和“神奇”的方法来做到这一点,但这是我能想到的最好的方法:

获取单个随机元素:

list |> Enum.shuffle |> hd
#=> 4

注意:如果list 为空,则会出现异常

获取多个随机元素:

list |> Enum.shuffle |> Enum.take(3)
#=> [7, 1, 5]

【讨论】:

  • 如果您收到类似“警告:erlang:now/0: Deprecated BIF. See the "Time and Time Correction in Erlang" Chapter of the ERTS User's Guide."之类的警告,像这样的种子改为::random.seed(:os.timestamp)
  • 从 Elixir 1.2 开始,您不需要调用 :random.seed/1,因为 Elixir 为此使用了新的 rand 模块。
  • 您好,这是上述代码的作者。 Enum.random / take_random 最初被称为 sample(就像在 Ruby 中一样)并被合并到 Elixir 1.1,后来更名。值得一提的是,使用reservoir sampling 算法的一个版本,关于可枚举的大小它是O(n)。这是我对 Elixir 标准库的第一个贡献——非常好的体验,人们在评论、讨论和整个工作流程方面都有很好的标准。我真的建议在那里做出贡献。
【解决方案2】:

Elixir 1.0 中没有这个功能,所以你需要自己实现它,就像其他解决方案提到的那样。但是,Enum.random/1 将与 Elixir v1.1 一起提供:https://hexdocs.pm/elixir/Enum.html#random/1

【讨论】:

    【解决方案3】:

    另一种方法(仅对一个元素进行采样)是:

    list |> Enum.at(:random.uniform(length(list)) - 1)
    

    如果您使用的列表足够大,可能会对性能产生影响,因此可能比其他方法更可取。

    Gazler's comment 关于使用:random.seed(:erlang.now) 仍然适用。

    【讨论】:

      【解决方案4】:

      如果您运行的是较新版本的 Elixir,则在 Elixir v1.1 中添加了 Enum.take_random/2 函数。

      来自 Elixir 的 v1.1 documentation

      从集合中随机抽取项目。

      请注意,此函数将遍历整个集合以获取集合的随机子列表。如果你想要两个整数之间的随机数,最好的选择是使用 :random 模块。

      因此,回答问题,从列表中获取多个项目如下所示:

      list = [1,2,3,4,5,6,7]
      Enum.take_random(list, 3)
      #=> [2, 4, 1]
      

      或者,对于单个项目:

      list = [1,2,3,4,5,6,7]
      Enum.take_random(list, 1)
      #=> [1]
      

      【讨论】:

        猜你喜欢
        • 2018-02-12
        • 2013-01-13
        • 2018-10-19
        • 1970-01-01
        • 1970-01-01
        • 2018-04-18
        • 1970-01-01
        • 2014-09-22
        相关资源
        最近更新 更多