给定项目列表,我们如何过滤特定结构?
示例:
我们只需要列表中项目的%TL.DocumentAttributeFilename{}
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{}]
答案 0 :(得分:7)
您可以使用for
:
假设:
defmodule A do
defstruct [letter: :a]
end
defmodule B do
defstruct [letter: :b]
end
你可以这样做:
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}]
这是有效的,因为for
忽略了与给定模式不匹配的所有项目。
答案 1 :(得分:1)
您还可以使用Enum.filter
并使用具有多个主体的函数进行模式匹配:
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)
这特别有用,因为您可以使用项目的属性和防护进一步缩小范围:
Enum.filter(list, fn
%A{number: n} when n > 4 -> rem(n, 3) == 0
%B{number: n} when n < 2 -> true
_ -> false
end)
答案 2 :(得分:0)
您还可以使用Enum.filter
更清楚地执行操作:
Enum.filter( lst1, fn( x ) -> %TL.DocumentAttributeFilename{} == x end )
正如Dogbert观察到的那样,上面的表达式只会保留lst1
TL.DocumentAttributeFilename
结构中具有默认字段值的元素 - 而不是您要求的内容。
这是一个保留TL.DocumentAttributeFilename
所有lst1
结构的版本:
Enum.filter( lst1, fn( x ) -> x.__struct__ == TL.DocumentAttributeFilename end )