根据条件从结构列表中返回元素

时间:2018-01-20 01:03:41

标签: elixir

我有一个函数,它是一个名为Sandbox的结构列表。见下文:

defmodule Sandbox do

  defstruct description: nil, chance: nil

  def all, do: [
    %Sandbox{
      description: "Description 1",
      chance: [1..40]
    },
    %Sandbox{
      description: "Description 2",
      chance: [41..60]
    },
    %Sandbox{
      description: "Description 3",
      chance: [61..100]
    },
  ]

我想随机选择一个Sandbox,每个Sandbox都有一个特定的概率。我的计划是根据每个项目的期望概率为一个名为“机会”的属性分配一系列数字,如上所示。然后,我将从1到100随机生成一个数字,并将其与每个Sandboxes列表进行匹配,以找到获胜的Sandbox。该功能需要返回获胜的沙箱。

问题:

  1. 你能写出一个函数来执行匹配并返回正确的Sandbox吗?一段时间以来一直尝试各种组合,似乎无法弄明白。

  2. 有人能想到更简单的方法吗?我觉得我的问题过于复杂。

  3. 非常感谢帮助。

2 个答案:

答案 0 :(得分:3)

首先,你不应该在列表中包装范围。只需写下chance: 1..40chance: 41..60等。以下是如何生成随机整数然后选择正确的沙箱:

defmodule Sandbox do
  defstruct description: nil, chance: nil

  def all, do: [
    %Sandbox{
      description: "Description 1",
      chance: 1..40
    },
    %Sandbox{
      description: "Description 2",
      chance: 41..60
    },
    %Sandbox{
      description: "Description 3",
      chance: 61..100
    },
  ]

  def random do
    rand = :rand.uniform(100)
    Enum.find(all(), fn %{chance: chance} -> rand in chance end)
  end
end
  

有人能想到更简单的方法吗?我觉得我的问题过于复杂。

这种方法对我来说很好看。如果性能是一个问题,那么将列表存储在树状数据结构中应该更快,我们可以比迭代每个元素更快地跳到右chance

答案 1 :(得分:2)

您可能遇到问题,因为chancerange内的list

这应该做你想要的:

defmodule Sandbox do

  defstruct description: nil, chance: nil

  def all, do: [
    %Sandbox{
      description: "Description 1",
      chance: 1..40
    },
    %Sandbox{
      description: "Description 2",
      chance: 41..60
    },
    %Sandbox{
      description: "Description 3",
      chance: 61..100
    },
  ]

  @doc "Select a sandbox given a random value between 1 and 100"
  def find(r) do
    all() |> Enum.find(fn s -> r in s.chance end)
  end

  @doc "Select a sandbox at random"
  def random() do
    :rand.uniform(100) |> find()
  end
end