使用Elixir从列表构造一个n长度的随机字符串

时间:2015-11-14 20:13:04

标签: functional-programming elixir

我有一个我想要使用的字符串列表构造一个n长度的新字符串。我如何从列表中随机选择一个元素,并将它们附加到字符串中,直到我达到所需的长度?

parts = ["hello", "world", "foo bar", "baz"]
n = 25
# Example: "foo bar hello world baz baz"

2 个答案:

答案 0 :(得分:7)

您需要使用Stream模块生成无限序列。一种方法可以是:

Stream.repeatedly(fn -> Enum.random(["hello", "world", "foo bar", "baz"]) end)
|> Enum.take(25)

这是elixir 1.1 due Enum.random/1。请查看Stream模块文档。

更新1:

用同样的方法来表示:

defmodule CustomEnum do
  def take_chars_from_list(list, chars) do
    Stream.repeatedly(fn -> Enum.random(list) end)
    |> Enum.reduce_while([], fn(next, acc) ->
      if String.length(Enum.join(acc, " ")) < chars do
        {:cont, [next | acc]} 
      else
        {:halt, Enum.join(acc, " ")}
      end
    end)
    |> String.split_at(chars)
    |> elem(0)
  end
end

n之后,这一条曲线变焦。

答案 1 :(得分:5)

这是我的用法,它使用尾递归:

defmodule TakeN do
    def take(list, n) do
        if length(list) == 0 do
            :error
        else
            do_take(list, n, [])
        end
    end

    defp do_take(_, n, current_list) when n < 0 do
        Enum.join(current_list, " ")
    end

    defp do_take(list, n, current_list) do
        random = Enum.random(list)

        # deduct the length of the random element from the remaining length (+ 1 to account for the space)
        do_take(list, n - (String.length(random) + 1), [random|current_list])
    end
end

并称之为:

iex > TakeN.take(["hello", "world", "foo bar", "baz"], 25)
"foo bar baz baz hello hello"