Elixir嵌套Map的Enum.filter使用问题及错误代码解析
Elixir嵌套Map过滤失效?来拆解问题和修复方案
你手里有这样的嵌套Map列表:
[%{test: %{"one" => 1, "three" => 3, "two" => 2}}, ...]
然后写了这段结合Enum.filter和Enum.each的代码,结果完全没起到过滤作用:
Enum.filter([map], fn(number) -> Enum.each(number.test, fn {k, v} -> v == 4 end) end)
为啥这段代码没用?
核心坑点就在**Enum.each/2的返回值**上:
Enum.each本来就是用来做「遍历执行副作用」的(比如打印内容),不管你在里面写什么判断逻辑,它最后都会返回:ok这个原子。- 但
Enum.filter要求过滤函数返回布尔值(true/false)来决定留不留元素。在Elixir里,:ok会被当作true处理,所以你的过滤函数相当于永远返回true,所有元素都被保留了,自然看不到过滤效果。
正确的嵌套Map过滤写法
我们需要换成能返回布尔值的遍历函数,比如Enum.any?/2或者Enum.all?/2,根据你的实际需求选:
需求1:保留test里至少有一个值等于4的元素
用Enum.any?,只要找到一个符合条件的键值对就返回true:
# 注意这里把[map]改成你的实际列表变量,比如map_list Enum.filter(map_list, fn item -> Enum.any?(item.test, fn {_k, v} -> v == 4 end) end)
需求2:保留test里所有值都等于4的元素
用Enum.all?,只有所有键值对都满足条件才返回true:
Enum.filter(map_list, fn item -> Enum.all?(item.test, fn {_k, v} -> v == 4 end) end)
额外补充:如果是精确匹配某个键的值
要是你明确要找test里键为"four"且值为4的元素,其实不用遍历,直接取Map的键判断更高效:
Enum.filter(map_list, fn item -> Map.get(item.test, "four") == 4 end)
内容的提问来源于stack exchange,提问作者lapinkoira
相关产品推荐
相关产品推荐

