Anton Maminov
Anton Maminov

Reputation: 532

Elixir: extract element from nested lists

I have the following JSON file with some mixed data.

For example, I want to extract from social_link link for Facebook.

[
  [
    "social_links",
    [
      {
        "image":"http://example.com/icons/facebook.svg",
        "link":"https://www.facebook.com/Example",
        "alt":"Facebook"
      },
      {
        "image":"http://example.com/icons/twitter.svg",
        "link":"https://twitter.com/example",
        "alt":"Twitter"
      },
      {
        "image":"http://example.com/icons/linkedin.svg",
        "link":"https://www.linkedin.com/company/example",
        "alt":"Linkedin"
      },
      {
        "image":"http://example.com/icons/icons/rounded_googleplus.svg",
        "link":"https://plus.google.com/+example",
        "alt":"Google Plus"
      }
    ]
  ]
]

In Ruby we can get data from nested data structures using following code:

hsh = JSON.parse str
hsh.select{ |k, _| k == "social_links" }[0][1].find { |k, _| k["alt"] == "Facebook"}["link"]
=> "https://www.facebook.com/Example"

How to do the same thing in Elixir? What is the best practice to extract data from nested structs?

Upvotes: 0

Views: 565

Answers (1)

Dogbert
Dogbert

Reputation: 222428

I'd do it like this using Poison for the parsing:

[_, links] = Poison.decode!(json) |> Enum.find(&match?(["social_links" | _], &1))
link = Enum.find_value(links, fn %{"alt" => "Facebook", "link" => link} -> link end)

Full code:

json = """
[
  [
    "social_links",
    [
      {
        "image":"http://example.com/icons/facebook.svg",
        "link":"https://www.facebook.com/Example",
        "alt":"Facebook"
      },
      {
        "image":"http://example.com/icons/twitter.svg",
        "link":"https://twitter.com/example",
        "alt":"Twitter"
      },
      {
        "image":"http://example.com/icons/linkedin.svg",
        "link":"https://www.linkedin.com/company/example",
        "alt":"Linkedin"
      },
      {
        "image":"http://example.com/icons/icons/rounded_googleplus.svg",
        "link":"https://plus.google.com/+example",
        "alt":"Google Plus"
      }
    ]
  ]
]
"""

[_, links] = Poison.decode!(json) |> Enum.find(&match?(["social_links" | _], &1))
link = Enum.find_value(links, fn %{"alt" => "Facebook", "link" => link} -> link end)
IO.puts link

Output:

https://www.facebook.com/Example

Upvotes: 2

Related Questions