列表追加不在案例匹配内工作?

时间:2018-01-19 16:39:08

标签: elixir

我正在尝试根据匹配更新两个列表,但列表一直是空的。

test_list = []
other_list = []
Enum.map(some_maps, fn some_map ->
  case some_map do
    %{"test" => item} -> test_list ++ [item]
    %{"test2" => item} -> other_list ++ [item]
  end
end)

我还尝试了test_list ++ itemtest_list = test_list + [item]

我怎么能接近这个?

2 个答案:

答案 0 :(得分:4)

Elixir中的变量是不可变的,因此您无法像这样修改它。我这样做:

some_maps = [%{"test" => 1}, %{"test2" => 2}, %{"test" => 3}]

test_list = for %{"test" => item} <- some_maps, do: item
other_list = for %{"test2" => item} <- some_maps, do: item

IO.inspect test_list
IO.inspect other_list
[1, 3]
[2]

如果你只想迭代一次地图,你也可以在这里使用Enum.reduce/3,但这样做可能足够好而且更优雅。

以下是Enum.reduce/3

的使用方法
some_maps = [%{"test" => 1}, %{"test2" => 2}, %{"test" => 3}]

{test_list, other_list} = Enum.reduce(some_maps, {[], []}, fn
  %{"test" => item}, {t, o} -> {[item | t], o}
  %{"test2" => item}, {t, o} -> {t, [item | o]}
end)

test_list = Enum.reverse(test_list)
other_list = Enum.reverse(other_list)

IO.inspect test_list
IO.inspect other_list

输出与以前相同。

PS:请在将来发布一个完整的示例,在这种情况下,这意味着some_maps的示例值。

答案 1 :(得分:1)

虽然@Dogbert的答案和往常一样完美,但是有一个明确专用的函数Enum.split_with/2可以完全按照你想要的那样做,即拆分可枚举的函数:

iex|1 ▶ some_maps = [%{"test" => 1}, %{"test2" => 2}, %{"test" => 3}]
#⇒ [%{"test" => 1}, %{"test2" => 2}, %{"test" => 3}]
iex|2 ▶ Enum.split_with(some_maps, fn 
...|2 ▶ %{"test" => _} -> true                          
...|2 ▶ %{"test2" => _} -> false
...|2 ▶ end)
#⇒ {[%{"test" => 1}, %{"test" => 3}], [%{"test2" => 2}]}

在这种特殊情况下,理解肯定是规则,但在某些情况下它可能会有所帮助。要获取值,应在结果列表中明确获取Map.values/1