Charles Okwuagwu
Charles Okwuagwu

Reputation: 10866

ELIXIR: how to Filter a list for a specific struct

Given a list of items, how may we filter for a specific struct?

Example:

We need only %TL.DocumentAttributeFilename{} from the items in the list

 lst1 = [%TL.DocumentAttributeImageSize{h: 1280, w: 960}, %TL.DocumentAttributeFilename{file_name: "422305695_81769.jpg"}]
 lst2 = [%TL.DocumentAttributeVideo{duration: 7, h: 224, w: 264}, %TL.DocumentAttributeFilename{file_name: "animation.gif.mp4"}, %TL.DocumentAttributeAnimated{}]

Upvotes: 1

Views: 3502

Answers (3)

Yuri
Yuri

Reputation: 17502

You can also use Enum.filter and pattern match using function with multiple bodies:

list = [%A{number: 1}, %B{number: 2}, %A{number: 3}, %A{number: 4}, %B{number: 5}, %A{number: 6}]

Enum.filter(list, fn
  %A{} -> true
  _ -> false
end)

This is particularly useful because you can further narrow down using item's properties and guards:

Enum.filter(list, fn
  %A{number: n} when n > 4 -> rem(n, 3) == 0
  %B{number: n} when n < 2 -> true
  _ -> false
end)

Upvotes: 5

krychu
krychu

Reputation: 992

You can also use Enum.filter to make it clearer what operation takes place:

Enum.filter( lst1, fn( x ) -> %TL.DocumentAttributeFilename{} == x end )

As Dogbert observed the above expression will keep only those elements of lst1 that are TL.DocumentAttributeFilename structs with default field values - not what you asked for.

Here's a version that will keep all TL.DocumentAttributeFilename structs of lst1:

Enum.filter( lst1, fn( x ) -> x.__struct__ == TL.DocumentAttributeFilename end )

Upvotes: 0

Dogbert
Dogbert

Reputation: 222118

You can use for for this:

Given:

defmodule A do
  defstruct [letter: :a]
end

defmodule B do
  defstruct [letter: :b]
end

You can do:

iex(1)> list = [%A{}, %B{}, %A{}, %A{}, %B{}]
[%A{letter: :a}, %B{letter: :b}, %A{letter: :a}, %A{letter: :a}, %B{letter: :b}]
iex(2)> for %A{} = a <- list, do: a
[%A{letter: :a}, %A{letter: :a}, %A{letter: :a}]

This works because for ignores all items that don't match the given pattern.

Upvotes: 7

Related Questions