我是elixir的新手,我正在试图找出重写这种红宝石方法的正确方法:
def filter_events(events)
events.select { |event| event[:id].present? && event[:vhost].present? }
end
在长生不老药中。这就是我到目前为止所做的:
def filter_events(events) do
Enum.filter(events, &(Map.has_key?(&1, :id) && Map.has_key?(&1, :vhost)))
end
有更好/更惯用的方法吗?
答案 0 :(得分:3)
你的榜样很短暂,并不重要;它是可读的。但是,大多数示例(包括the ones in the docs)都使用内联/匿名函数:
Enum.filter(events, fn(event) ->
Map.has_key?(event, :vhost) and Map.has_key?(event, :id)
end)
如果您正在寻找更聪明的东西,可以使用Kernel.match?()
模式匹配。
Enum.filter(events, &match?(%{id: _, vhost: _}, &1))
或内联函数:
Enum.filter(events, fn(event) -> match?(%{id: _, vhost: _}, event) end)
由于您正在尝试检查密钥是否存在且其值不为空,因此以下内容应该有效:
Enum.filter(events, fn(event) ->
!is_nil(event[:vhost]) and !is_nil(event[:id])
end)
答案 1 :(得分:1)
为了多样性,我会在这里提出这个答案。在我的理解中,最常用的方法是在过滤功能内进行模式匹配。它可能看起来更长,但更灵活。如果您的地图可能包含所需键的合法nil
值(不是您的情况,可能,但仍然如此),它可以更好地处理。
def filter_events(events) do
Enum.filter(events, fn
%{id: nil} -> false # or true if it might be nil
%{vhost: nil} -> false # or true if it might be nil
%{id: _, vhost: _} -> true
_ -> false
end)
end
在您的情况下,nil
值无效并且应被视为缺少值时,可能会简化为:
def filter_events(events) do
Enum.filter(events, fn
%{id: id, vhost: vhost} when not is_nil(id)
and not is_nil(vhost) -> true
_ -> false
end)
end
另一种方法是使用Kernel.for/1
理解:
def filter_events(events) do
for %{id: id, vhost: vhost} = e when
not is_nil(id) and
not is_nil(vhost) <- events, do: e
end
或者,没有模式匹配(较不惯用):
def filter_events(events) do
for e <- events, !is_nil(e[:id]), !is_nil(e[:vhost]), do: e
end
或者,如果您不期望nil
值,只需:
def filter_events(events) do
for %{id: _, vhost: _} = e <- events, do: e
end