如何在elixir的循环中增加一个值

我正在尝试计算从 range1 到 range4 的每个范围内数字的次数。范围1是1-10,范围2是11-20,范围3是21-30,范围4是31-40。我在下面的是:

range1=0
range2=0
range3=0
range4=0
arr=[1,11,2,22,33,23]
Enum.each arr, fn(x) ->
  if x >=1 and x<=10 do
    range1=range1+1
  end
  if x>=11 and x<=20 do
    range2=range2+1
  end
  if x>=21 and x<=30 do
    range3=range3+1
  end
  if x>=31 and x<=40 do
    range4=range4+1
  end
end 

IO.puts range1
IO.puts range2
IO.puts range3
IO.puts range4

但是,当我运行它时,它会说它们都是 0。为什么要这样做?

回答

Elixir是一种不可变的语言。不能改变变量的值。曾经。

人们可能会重新绑定一个变量,但它永远不会泄漏到外部作用域,所以您所做的基本上是rangeN 在内部作用域中绑定以立即丢弃它。来自外部作用域的变量(巧合地具有相同的名称)永远不会改变。

我们在elixir 中也没有循环。我们改用 map/reduce。

也就是说,你需要的是 Enum.reduce/3

Enum.reduce(
    [1,11,2,22,33,23], # input
    {0, 0, 0, 0},      # initial accumulator
    fn x, {acc1, acc2, acc3, acc4} ->
  cond do
    x>=1 and x<=10 -> {acc1 + 1, acc2, acc3, acc4}
    x>=11 and x<=20 -> {acc1, acc2 + 1, acc3, acc4}
    x>=21 and x<=30 -> {acc1, acc2, acc3 + 1, acc4}
    x>=31 and x<=40 -> {acc1, acc2, acc3, acc4 + 1}
  end
end)
#? {2, 1, 2, 1}

该函数总是返回最后一个表达式的结果,因此我们在cond/1这里使用。但是惯用的方法是使用带有警卫的累积函数的多个子句。

Enum.reduce [1,11,2,22,33,23], {0, 0, 0, 0}, fn 
  x, {acc1, acc2, acc3, acc4} when x>=1 and x<=10 ->
    {acc1 + 1, acc2, acc3, acc4}
  x, {acc1, acc2, acc3, acc4} when x>=11 and x<=20 ->
    {acc1, acc2 + 1, acc3, acc4}
  x, {acc1, acc2, acc3, acc4} when x>=21 and x<=30 ->
    {acc1, acc2, acc3 + 1, acc4}
  x, {acc1, acc2, acc3, acc4} when x>=31 and x<=40 ->
    {acc1, acc2, acc3, acc4 + 1}
end 

要获取值,可以使用模式匹配结果或使用Kernel.elem/2.

{less_that_10, _, _, _} =
  Enum.reduce(...)
less_than_10
#? 2

input
|> Enum.reduce(...)
|> elem(0)
#? 2


以上是如何在elixir的循环中增加一个值的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>