Running_total 变量被重置 - 为什么?

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

我对 Elixir 非常陌生

运行总计变量在运行后重置为零 if 语句。我该如何解决这个问题?

我知道 Elixir 中的一切都是“不可变的”,但我知道 并没有真正帮助我。

defmodule Solution do
  @spec roman_to_int(s :: String.t) :: integer
  def roman_to_int(s) do
    roman_map = %{
      "I" => 1,
      "V" => 5,
      "X" => 10,
      "L" => 50,
      "C" => 100,
      "D" => 500,
      "M" => 1000
    }

    running_total = 0
    max_value = -100

    s = String.reverse(s)
    IO.puts("String is now: #{s}")

    String.graphemes(s) |> Enum.each(fn char ->
      curr_val = roman_map[char]
      IO.puts("processing char: #{char}")

      if curr_val >= max_value do
        running_total = running_total + curr_val
        IO.puts("greater than, running total is now: #{running_total}")
      end
      IO.puts("after greater than, running total is now: #{running_total}")

      if curr_val < max_value do
        running_total = running_total - curr_val
        IO.puts("less than, running total is now: #{running_total}")
      end

      if curr_val > max_value do
         max_value = curr_val
      end

    end)

    running_total
  end
end

IO.puts(Solution.roman_to_int("XIV"))
elixir
1个回答
0
投票

“一切都是一成不变的”实际上是最重要的一句话。每次分配给一个变量时,它都会创建一个新变量,如果它位于 lambda 或像

if
表达式这样的块内,则新变量的作用域为该块。

在机械层面上,这意味着,如果你想“重新分配”一个变量,你需要覆盖两个分支 if

if
表达式(在 Elixir 中它是一个表达式而不是语句)并分配结果.

running_total = if curr_val >= max_value do
  running_total + curr_val
else
  running_total
end

然而,lambda 也存在类似的问题。 lambda 无法修改外部作用域的变量,因此需要从 lambda 函数返回新状态。

Enum.reduce/3
采用初始状态并允许函数返回新状态。


我该如何修改这个?匿名函数保留两个运行状态,您将其标记为

running_total
max_value
。您需要将它们作为函数的参数,并从函数返回更新的值。
Enum.reduce/3
将返回最终状态。

{running_total, _} =  String.graphemes(s)
  |> Enum.reduce({0, -100}, fn char, {running_total, max_value} ->
       ...
       {running_total, max_value}
     end)

running_total

在函数内,您需要确保重新分配变量,无论采用

if
条件的哪条路径。

running_total = if curr_val >= max_value do
  running_total + curr_val
else
  running_total - curr_val
end
max_value = max(curr_val, max_value)

请注意,

max_value
不存在于匿名函数之外。函数体无法修改它,并且它不是最终返回的一部分。作为
reduce
调用迭代之间传递的状态的一部分,它确实会返回,但可以在那里忽略。

© www.soinside.com 2019 - 2024. All rights reserved.