比较和减少两个列表中的对

时间:2017-08-29 09:07:03

标签: functional-programming elixir

鉴于Alice的三元组和Bob的三元组(列表),我需要比较每个元素,以便alice_triplet[i]> bob_triplet[i],爱丽丝的得分加1,反之亦然。

我有这段代码:

def main do
    alice_triplet = [5, 6, 7]
    bob_triplet = [3, 6, 10]

    alice_score = 0
    bob_score = 0

    Enum.zip(alice_triplet, bob_triplet) 
    |> Enum.each(fn 
        tuple when elem(tuple, 0) > elem(tuple, 1) -> alice_score = alice_score + 1
        tuple when elem(tuple, 1) > elem(tuple, 0) -> bob_score = bob_score + 1
        _ -> nil end)

    IO.puts alice_score
    IO.puts bob_score

end

但是,输出是:

0
0

为什么呢?我认为这是关于可变范围的,因为我收到了这个警告:

  

警告:变量" alice_score"未使用的解决方案.ex:12

     

警告:变量" bob_score"未使用的解决方案.ex:13

是否有更多功能性"这样做的方法?我正在学习Elixir(实际上是FP),所以任何建议都会受到赞赏。

1 个答案:

答案 0 :(得分:2)

语句alice_score = alice_score + 1不会修改外部alice_score,它会创建一个新的本地alice_score,其值设置为外部值+ 1.这已在{{3 }} many。解决方案几乎总是将Enum.reduce/3与您需要更改的状态一起用作累加器。

以下是如何将其应用于您的代码:

alice_triplet = [5, 6, 7]
bob_triplet = [3, 6, 10]

{alice_score, bob_score} = Enum.zip(alice_triplet, bob_triplet) |>
Enum.reduce({0, 0}, fn 
  tuple, {as, bs} when elem(tuple, 0) > elem(tuple, 1) -> {as + 1, bs} 
  tuple, {as, bs} when elem(tuple, 1) > elem(tuple, 0) -> {as, bs + 1}
  _, {as, bs}  -> {as, bs}
end)

IO.puts alice_score
IO.puts bob_score

您还可以使用模式匹配而不是elem/2来简化代码(elem/2很少用于惯用的Elixir代码中):

alice_triplet = [5, 6, 7]
bob_triplet = [3, 6, 10]

{alice_score, bob_score} = Enum.zip(alice_triplet, bob_triplet) |> 
Enum.reduce({0, 0}, fn 
  {a, b}, {as, bs} when a > b -> {as + 1, bs}
  {a, b}, {as, bs} when b > a -> {as, bs + 1}
  _, {as, bs}  -> {as, bs}
end)

IO.puts alice_score
IO.puts bob_score

两种情况下的输出都是

1
1