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

问题描述 投票:1回答:2

我有一个函数,它是一个名为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. 你能写出一个函数来执行匹配并返回正确的沙盒吗?已经尝试了一段时间的各种组合,似乎无法搞清楚。
  2. 谁能想到一个更简单的方法呢?我觉得我过于复杂了这个问题。

真的很感激帮助。

elixir
2个回答
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


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
© www.soinside.com 2019 - 2024. All rights reserved.