通过传递给当前函数的字段的子集匹配结构
Matching a struct by a subset of its fields passed into the current function
我正在构建过滤 API。简化事情,我有一些类似于接受结构列表和过滤器映射的函数的东西。我的问题是 Enum.filter
与 &match?
的配对在传入函数参数时不起作用:
def filter_structs(structs, filters) do
# this always returns []
structs |> Enum.filter(&match?(^filters, &1))
end
但如果我对过滤器进行硬编码,一切正常:
def filter_structs(structs, _filters) do
structs |> Enum.filter(&match?(%{some_field: true}, &1))
end
我有这个解决方法,但它不是很好...没有更好的解决方案吗?
def filter_structs(structs, filters) do
structs
|> Enum.filter(fn s ->
Map.equal?(filters, s |> Map.take(filters |> Map.keys))
end)
end
映射可以在变量 key
上使用 %{^key => _}
和变量键值对使用 %{^key => ^value}
.
进行模式匹配
使用 match?(^filters, map)
匹配整个地图将仅 return true
如果 map === filters
,不包含它。
以下实现利用了模式匹配,可能更清楚其意图:
def filter_structs(structs, filters) do
Enum.filter(structs, fn struct ->
Enum.all?(filters, fn {field, value} ->
match?(%{^field => ^value}, struct)
end)
end)
end
+1 到 sabiwara 的回答。
我觉得你的版本也不错。虽然我可能会在没有管道的情况下编写它:
def filter_structs(structs, filters) do
keys = Map.keys(filters)
Enum.filter(structs, &(filters === Map.take(&1, keys)))
end
我正在构建过滤 API。简化事情,我有一些类似于接受结构列表和过滤器映射的函数的东西。我的问题是 Enum.filter
与 &match?
的配对在传入函数参数时不起作用:
def filter_structs(structs, filters) do
# this always returns []
structs |> Enum.filter(&match?(^filters, &1))
end
但如果我对过滤器进行硬编码,一切正常:
def filter_structs(structs, _filters) do
structs |> Enum.filter(&match?(%{some_field: true}, &1))
end
我有这个解决方法,但它不是很好...没有更好的解决方案吗?
def filter_structs(structs, filters) do
structs
|> Enum.filter(fn s ->
Map.equal?(filters, s |> Map.take(filters |> Map.keys))
end)
end
映射可以在变量 key
上使用 %{^key => _}
和变量键值对使用 %{^key => ^value}
.
使用 match?(^filters, map)
匹配整个地图将仅 return true
如果 map === filters
,不包含它。
以下实现利用了模式匹配,可能更清楚其意图:
def filter_structs(structs, filters) do
Enum.filter(structs, fn struct ->
Enum.all?(filters, fn {field, value} ->
match?(%{^field => ^value}, struct)
end)
end)
end
+1 到 sabiwara 的回答。
我觉得你的版本也不错。虽然我可能会在没有管道的情况下编写它:
def filter_structs(structs, filters) do
keys = Map.keys(filters)
Enum.filter(structs, &(filters === Map.take(&1, keys)))
end