我对Elixir不熟悉,我试图从一个非常嵌套的地图中获取一些文本。
所以我正在对此link进行get请求,并使用Jason.decode对其进行解码。
我想做的是遍历它并获取每个文本值(sections-> 0-> content-> 0-> text)。
最后,我只希望它是所有文本值的大字符串
(链接始终可以更改,因此可能会有更多地图等)
谢谢!
答案 0 :(得分:0)
Elixir提供(通过erlang)一些函数,这些函数可以反映数据结构以检查其类型,例如is_map/1, is_list/1, is_number/1, is_boolean/1, is_binary/1, is_nil/1
等。来自docs
尝试处理您将在响应中使用的常见数据类型。它们可以是图元,图或图元列表,其中图元如布尔值,数字或字符串。
编写一个函数,该函数尝试递归地遍历您获得的数据结构,直到到达原始数据,然后返回经过字符串化的原始数据
例如对于地图,请遍历每个值(忽略键),如果该值不是原始值,则使用该节点递归调用该函数,直到到达原始值并可以返回字符串化的值为止。列表类似
类似的事情应该起作用:
defmodule Test do
def stringify(data) do
cond do
# <> is concatenation operator
# -- call stringify() for every value in map and return concatenated string
is_map(data) -> data |> Map.values |> Enum.reduce("", fn x, acc -> acc <> stringify(x) end)
# -- call stringify() for every element in list and return concatenated string
is_list(data) -> data |> Enum.reduce("", fn x, acc -> acc <> stringify(x) end)
is_boolean(data) -> to_string(data)
is_number(data) -> to_string(data)
is_binary(data) -> data # elixir strings are binaries
true -> ""
end
end
end
# For testing...
{:ok, %HTTPoison.Response{body: sbody}} = HTTPoison.get("https://pokemon.fandom.com/api/v1/Articles/AsSimpleJson?id=2409")
{:ok, body} = Poison.decode(sbody)
Test.stringify(body)
# returns
"Cyndaquil (Japanese: ヒノアラシ Hinoarashi) is the Fire-type Starter..."
答案 1 :(得分:0)
您可以将Enum
与管道运算符|>
配合使用,以枚举数据结构并提取所需的部分。
例如:
def pokedex(id) do
HTTPoison.get!("https://pokemon.fandom.com/api/v1/Articles/AsSimpleJson?id=#{id}")
|> Map.get(:body)
|> Jason.decode!()
|> Map.get("sections")
|> Enum.reject(fn %{"content" => content} -> content === [] end)
|> Enum.flat_map(fn %{"content" => content} ->
content
|> Enum.filter(fn %{"type" => type} -> type in ["text", "paragraph"] end)
|> Enum.map(fn %{"text" => text} -> text end)
end)
|> Enum.join("\n")
end
明细:
Map.get("sections")
选择sections
的内容。Enum.reject(...)
忽略空白部分。Enum.flat_map
遍历各节,获取每个节的contents
,使用内部函数对其进行转换,然后将结果展平为一个列表。
Enum.filter(...)
仅处理type
属性为text
或paragraph
的内容。Enum.map
从每个内容映射中提取text
属性。Enum.join
用换行符将结果字符串列表连接起来。