我通过帖子contacts = [%{"John" => ["0724573977"]}, %{"Mary" => ["0724573111", "0744556778"]}]
发送给我的这个结构基本上是一个联系人列表,每个联系人都是一个地图name => phone_numbers
我正在尝试列出包含所有电话号码的列表,忽略任何名称,只是一个数字列表:
a = [%{"1" => ["0724573977"]}, %{"2" => ["0724573111", "0744556778"]}]
p = Enum.reduce a, [], fn(contact, acc) ->
for {_record_id, phones} <- contact do
for phone <- phones do
acc ++ phone
end
end
end
IO.inspect p
这个产生:[[[["0724573977"] | "0724573111"], [["0724573977"] | "0744556778"]]]
这是奇怪但我不知道我做错了什么。
答案 0 :(得分:5)
已经发布了许多正确的答案,但我认为我会发布我的首选解决方案:使用for
和3 <-
:
iex(1)> contacts = [%{"1" => ["0724573977"]}, %{"2" => ["0724573111", "0744556778"]}]
[%{"1" => ["0724573977"]}, %{"2" => ["0724573111", "0744556778"]}]
iex(2)> for contact <- contacts, {_, phones} <- contact, phone <- phones, do: phone
["0724573977", "0724573111", "0744556778"]
(我特别不喜欢基于List.flatten/1
的解决方案,因为如果最后一级数据是列表而不是字符串,它们将不会以相同的方式工作。这些函数会在任何深度处平展每个列表。这无关紧要对于这种特殊情况,因为你的最后一级数据是一个字符串列表。)
答案 1 :(得分:3)
要获得一个可能使用的数字列表:
contacts
|> Enum.map(&Map.values/1)
|> List.flatten
#⇒ ["0724573977", "0724573111", "0744556778"]
要用数字替换名称,可以在链的中间使用Enum.with_index
。
答案 2 :(得分:2)
更容易做到:
a
|> Enum.flat_map(&Map.to_list/1)
|> Enum.flat_map(a, fn {_record_id, phones} -> phones end)
您尝试过的代码的问题是for
的每次迭代都会在新列表中生成一个元素,另外因为Elixir是不可变的,所以您实际上并没有更改acc
正在创建的内容将每个电话号码附加到同一列表的元素,因此最终会得到意外的列表列表。
答案 3 :(得分:2)
这可能不是惯用的Elixir,因为我是该语言的新手,但这对我有用:
iex(11)> List.flatten(Enum.map(a, fn(x) -> Map.values(x) end))
["0724573977", "0724573111", "0744556778"]