如何在Elixir中筛选地址含指定城镇的人员信息
问题修复与Elixir惯用实现
问题原因
你当前的代码通过两层for推导式生成了列表的列表:外层循环每个城镇,内层循环所有人并筛选匹配项,因此结果中会包含对应每个城镇的匹配列表(比如"denver"没有匹配,就返回空数组),最终形成嵌套结构。
快速修复现有代码
如果要基于你的现有代码修改,只需在最后添加List.flatten/1将嵌套列表展开,同时可以用Enum.uniq/1避免同一人因匹配多个城镇而重复出现:
defmodule Locator do def check_towns(people_details, list_of_towns) do for town <- list_of_towns do for person <- people_details do if String.contains?(person.address, town) do person end end |> Enum.reject(&is_nil/1) end |> List.flatten() |> Enum.uniq() end end
更符合Elixir惯用写法的实现
换一种思路:直接遍历人员列表,检查每个人员的地址是否包含目标城镇列表中的任意一个。这种方式只需要遍历一次人员列表,逻辑更直观,性能也更优:
defmodule Locator do def check_towns(people_details, list_of_towns) do Enum.filter(people_details, fn person -> Enum.any?(list_of_towns, &String.contains?(person.address, &1)) end) end end
代码说明
Enum.filter/2:遍历people_details,保留满足条件的人员Enum.any?/2:检查当前人员的地址是否包含list_of_towns中的任意一个城镇,只要有一个匹配就返回true- 使用
person.address代替person[:address]:对于map,直接用点语法更符合Elixir风格
测试后会返回你预期的结果:
[ %{name: "joe", address: "123 main st, sacramento"}, %{name: "sam", address: "789 main st, nashville"} ]
内容的提问来源于stack exchange,提问作者thirtythirty
相关产品推荐
相关产品推荐

