Eyal Zinder
Eyal Zinder

Reputation: 664

Acting on filtered elements in a list

I have a collection of records from a data source denoting {:person, _} for person, {:dog, _} for dog, etc. I'd like to return a modified version of the record based on the condition that the record is that of ':person'.

    db = [
{:dog, %{name: "Sparky", age: 4}}, 
{:person, %{name: "Jeff", age: 34}}, 
{:person, %{name: "Suzan", age: 41}}, 
{:dog, %{name: "Bella", age: 8}}
]

I'd like to return:

[{:person, "Jeff", 34}, {:person, "Suzan", 41}] 

I've tried:

db |> Enum.map(fn {:person, data} -> {:person, data.name, data.age} end) 

But I'm erroring on non-match for :dog

Any advice?

Upvotes: 1

Views: 95

Answers (2)

Mike Quinlan
Mike Quinlan

Reputation: 2882

One easy way to do this is by using a Comprehension.

for {:person, data} <- db, do: {:person, data.name, data.age}

Comprehensions are a powerful tool in Elixir that allow you to filter out data from a list with a match spec (among other things). The above code snippet will only iterate over items in the list that are 2 element tuples, having the first element be the :person atom. All other entries are filtered out. Of course, comprehensions are more powerful than this. If you wanted to enforce that all records returned included a name and age attribute you could do something like this:

for {:person, %{age: age, name: name}} <- db, 
  is_integer(age), 
  is_binary(name), 
  do: {:person, name, age}

The above will only return entries that are 2 element tuples, having :person as the first element, :age and :name keys in the data, and where age is an integer and name is a binary.

Upvotes: 4

Karol Ostrowski
Karol Ostrowski

Reputation: 94

First You need to filter out elements You want to use, so it should be like this

db |> Enum.filter(fn data -> match?({:person, _}, data) end)
   |> Enum.map(fn {:person, data} -> {:person, data.name, data.age} end)

Map is just taking input elements and creates new Enum with returned values from function given as argument to map function.

Filter creates new Enum which contains only element where given function return true

Upvotes: 2

Related Questions