-1

我是 elixir 的新手,我正在尝试从非常嵌套的地图中获取一些文本。

因此,我正在对此链接发出获取请求,并使用 Jason.decode 对其进行解码。

我想要做的是迭代它并获取每个文本值(sections->0->content->0->text)。

最后,我只希望它是所有文本值的大字符串

(链接可以随时更改,因此可能会有更多地图等)

提前致谢!

4

3 回答 3

2

您可以使用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属性为textor的内容paragraph
    • Enum.maptext从每个内容映射中提取属性。
  • Enum.join用换行符连接生成的字符串列表。
于 2019-03-10T00:47:14.593 回答
1

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..."
于 2019-03-09T19:03:25.200 回答
0

如果可以选择为此任务使用外部包,您可以尝试我为此目的编写的包:Iteraptor.

它在嵌套的Elixir可枚举术语上提供迭代/映射/减少功能。

于 2019-03-10T06:51:30.053 回答