4

我正在尝试在 Elixir 中使用 Google Maps 地理编码 API,尽管我对这种语言有点陌生,所以使用嵌套数据结构让我望而却步。

我正在使用 HTTPotion 从地理编码端点获取 JSON,并使用 JSEX 将其解析为 Elixir 数据结构(一系列嵌套列表和元组)。

defmodule Geocode do
  def fetch do
    HTTPotion.start
    result = HTTPotion.get "http://maps.googleapis.com/maps/api/geocode/json?address=Fairfax,%20Vermont&sensor=false"
    json   = JSEX.decode result.body
  end
end

现在将以下内容分配给 json。

{:ok, [{"results", [[{"address_components", [[{"long_name", "Fairfax"}, {"short_name", "Fairfax"}, {"types", ["locality", "political"]}], [{"long_name", "Franklin"}, {"short_name", "Franklin"}, {"types", ["administrative_area_level_2", "political"]}], [{"long_name", "Vermont"}, {"short_name", "VT"}, {"types", ["administrative_area_level_1", "political"]}], [{"long_name", "United States"}, {"short_name", "US"}, {"types", ["country", "political"]}]]}, {"formatted_address", "Fairfax, VT, USA"}, {"geometry", [{"bounds", [{"northeast", [{"lat", 44.772892}, {"lng", -72.92268890000001}]}, {"southwest", [{"lat", 44.6330508}, {"lng", -73.08477409999999}]}]}, {"location", [{"lat", 44.6654963}, {"lng", -73.01032}]}, {"location_type", "APPROXIMATE"}, {"viewport", [{"northeast", [{"lat", 44.772892}, {"lng", -72.92268890000001}]}, {"southwest", [{"lat", 44.6330508}, {"lng", -73.08477409999999}]}]}]}, {"types", ["locality", "political"]}]]}, {"status", "OK"}]}

我想从这个嵌套数据结构中提取纬度和经度。我尝试过使用模式匹配,但由于结构相当复杂,相应的模式有点像噩梦。虽然以下工作它不可能是一个好的解决方案。

{_, [{_, [[_, _, { _, [{_, [{_, [{_, lat}, {_, lgn}]}, _]}, _, _, _] }, _]]}, _]} = json

所以我的问题是从 Elixir 中深度嵌套的数据结构中提取值的最佳方法是什么?任何朝着正确方向的解决方案或轻推将不胜感激。

4

3 回答 3

9

Check out the source to Seth Falcon's ej library:

https://github.com/seth/ej

It does more or less what you're wanting to do, using recursion.

I'm not an Elixir expert, but you might be able to just use that library directly.

于 2013-08-02T14:37:37.130 回答
5

ej 库看起来是个不错的选择,但另外我可能会马上切入数据结构的核心:

{:ok, [{"results", results}, {"status", status}]} = JSEX.decode result.body

或者如果你总是只使用第一个结果:

{:ok, [{"results", [geo_json | _]}, {"status", status}]} = JSEX.decode result.body

然后我会在 geo_json 数据结构上使用 ej 库。

于 2013-08-02T15:09:44.560 回答
0

您的JSEX.decode(result.body) 值格式更好:

{:ok,
 [
   {"results",
    [
      [
        {"address_components",
         [
           [
             {"long_name", "Fairfax"},
             {"short_name", "Fairfax"},
             {"types", ["locality", "political"]}
           ],
           [
             {"long_name", "Franklin"},
             {"short_name", "Franklin"},
             {"types", ["administrative_area_level_2", "political"]}
           ],
           [
             {"long_name", "Vermont"},
             {"short_name", "VT"},
             {"types", ["administrative_area_level_1", "political"]}
           ],
           [
             {"long_name", "United States"},
             {"short_name", "US"},
             {"types", ["country", "political"]}
           ]
         ]},
        {"formatted_address", "Fairfax, VT, USA"},
        {"geometry",
         [
           {"bounds",
            [
              {"northeast", [{"lat", 44.772892}, {"lng", -72.92268890000001}]},
              {"southwest", [{"lat", 44.6330508}, {"lng", -73.08477409999999}]}
            ]},
           {"location", [{"lat", 44.6654963}, {"lng", -73.01032}]},
           {"location_type", "APPROXIMATE"},
           {"viewport",
            [
              {"northeast", [{"lat", 44.772892}, {"lng", -72.92268890000001}]},
              {"southwest", [{"lat", 44.6330508}, {"lng", -73.08477409999999}]}
            ]}
         ]},
        {"types", ["locality", "political"]}
      ]
    ]},
   {"status", "OK"}
 ]}

with/1看起来很合适:

with {:ok, json}                              <- JSEX.decode(result.body),
     [{"results", results}, {"status", "OK"}] <- json,
     [[_, _, {"geometry", geometry}, _]]      <- results,
     [_, {"location", location}, _, _]        <- geometry,
     [{"lat", lat}, {"lng", lng}]             <- location                  do

     # Do something with `lat` and `lng` here.

end

或者可能:

{:ok, lat, lng} =
  with {:ok, json}                              <- JSEX.decode(result.body),
       [{"results", results}, {"status", "OK"}] <- json,
       [[_, _, {"geometry", geometry}, _]]      <- results,
       [_, {"location", location}, _, _]        <- geometry,
       [{"lat", lat}, {"lng", lng}]             <- location                  do

     {:ok, lat, lng}

  else

    _ -> {:error, "Failed to parse Google Maps API `geocode` response."}

  end
于 2021-10-06T17:01:29.803 回答