英文:
How to find all instances where a given value in a map matches any element in a list of strings
问题
尝试扩展我的Elixir工作能力,但我在使这个工作时遇到了问题。这是一个虚构的示例,简化了我面临的类似问题。给定一个城镇列表和一个人员及其地址列表,我该如何查找城镇字符串是否包含在名称和地址映射列表中。
list_of_towns = ["denver", "sacramento", "nashville"]
people_details = [
%{
name: "joe",
address: "123 main st, sacramento"
},
%{
name: "jack",
address: "456 international ave, oakland"
},
%{
name: "sam",
address: "789 main st, nashville"
}
]
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(fn x -> is_nil(x) end)
end
end
end
我希望这返回具有交集的映射列表:
[
%{
name: "joe",
address: "123 main st, sacramento"
},
%{
name: "sam",
address: "789 main st, nashville"
}
]
但实际上返回的是:
[
[],
[%{address: "123 main st, sacramento", name: "joe"}],
[%{address: "789 main st, nashville", name: "sam"}]
]
所以,我该如何清理它,以便不再有空数组,并且后续的结果也不再像数组一样包裹?另外,我相当肯定这个语法不太习惯,所以我会很高兴看到更好的方法。
英文:
Trying to expand my working ability with Elixir, and I'm having trouble getting this to work. This is a contrived example simplifying a similar problem I have. Given a list of towns and a list of people and addresses, how do I go about finding when one of the town strings is contained in the list of maps of name and address.
list_of_towns = ["denver", "sacramento", "nashville"]
people_details = [
%{
name: "joe",
address: "123 main st, sacramento"
},
%{
name: "jack",
address: "456 international ave, oakland"
},
%{
name: "sam",
address: "789 main st, nashville"
}
]
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(fn x -> is_nil(x) end)
end
end
end
I'd like this to return just the list of maps where the sets intersect
[
%{
name: "joe",
address: "123 main st, sacramento"
},
%{
name: "sam",
address: "789 main st, nashville"
}
]
but this returns
[
[],
[%{address: "123 main st, sacramento", name: "joe"}],
[%{address: "789 main st, nashville", name: "sam"}]
]
So how do I clean this up, so I don't have the empty array, and the subsequent results aren't wrapped like arrays as well?
Also, I'm pretty sure this syntax is idiomatically crap, so I'd be happy to see a better way.
答案1
得分: 2
不需要理解这里。当问题描述中包含“find”一词时,通常使用Enum.find/2
或Access
中的一个。
以下是完成任务的一种可能方式。
Enum.filter(people_details, fn %{address: address} ->
Enum.any?(list_of_towns, &String.contains?(address, &1))
end)
#⇒ [
# %{address: "123 main st, sacramento", name: "joe"},
# %{address: "789 main st, nashville", name: "sam"}
# ]
无论你是否仍然想要[滥用]理解,将其用作_过滤器_而不是另一个循环。
for person <- people_details,
List.last(String.split(person.address, ", ")) in list_of_towns,
do: person
#⇒ [
# %{address: "123 main st, sacramento", name: "joe"},
# %{address: "789 main st, nashville", name: "sam"}
# ]
英文:
One does not need a comprehension here. When the problem description contains “find” word, one usually uses either Enum.find/2
or Access
.
Here is one of possible ways to accomplish the task.
Enum.filter(people_details, fn %{address: address} ->
Enum.any?(list_of_towns, &String.contains?(address, &1))
end)
#⇒ [
# %{address: "123 main st, sacramento", name: "joe"},
# %{address: "789 main st, nashville", name: "sam"}
# ]
Whether you are still after [ab]using a comprehension, use it as filter, not as another loop.
for person <- people_details,
List.last(String.split(person.address, ", ")) in list_of_towns,
do: person
#⇒ [
# %{address: "123 main st, sacramento", name: "joe"},
# %{address: "789 main st, nashville", name: "sam"}
# ]
答案2
得分: 1
<!-- language-all: lang-elixir -->
You can do this using a comprehension like this:
for %{address: address} = person_detail <- people_details,
town <- list_of_towns,
String.contains?(address, town),
do: person_detail
It enumerates all the `person_detail` and `town` permutations, filters based on your condition, and returns the `person_details` that match. Note that it will return duplicates if an address matches multiple town strings - but that indicates a bug with your filter condition.
Result:
[
%{address: "123 main st, sacramento", name: "joe"},
%{address: "789 main st, nashville", name: "sam"}
]
However, I wouldn't write this code normally - the first part of Aleksei's answer is what I'd write too.
英文:
<!-- language-all: lang-elixir -->
You can do this using a comprehension like this:
for %{address: address} = person_detail <- people_details,
town <- list_of_towns,
String.contains?(address, town),
do: person_detail
It enumerates all the person_detail
and town
permutations, filters based on your condition, and returns the person_details
that match. Note that it will return duplicates if an address matches multiple town strings - but that indicates a bug with your filter condition.
Result:
[
%{address: "123 main st, sacramento", name: "joe"},
%{address: "789 main st, nashville", name: "sam"}
]
However, I wouldn't write this code normally - the first part of Aleksei's answer is what I'd write too.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论