如何找到地图中给定值与字符串列表中的任何元素匹配的所有实例。

huangapple go评论59阅读模式
英文:

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 = [&quot;denver&quot;, &quot;sacramento&quot;, &quot;nashville&quot;]

    people_details = [
      %{
        name: &quot;joe&quot;,
        address: &quot;123 main st, sacramento&quot;
      },
      %{
        name: &quot;jack&quot;,
        address: &quot;456 international ave, oakland&quot;
      },
      %{
        name: &quot;sam&quot;,
        address: &quot;789 main st, nashville&quot;
      }
    ]

    defmodule Locator do
      def check_towns(people_details, list_of_towns) do
        for town &lt;- list_of_towns do
          for person &lt;- people_details do
            if String.contains?(person[:address], town) do
              person
            end
          end
          |&gt; Enum.reject(fn x -&gt; is_nil(x) end)
        end
      end
    end

I'd like this to return just the list of maps where the sets intersect

    [
     %{
        name: &quot;joe&quot;,
        address: &quot;123 main st, sacramento&quot;
      },
      %{
        name: &quot;sam&quot;,
        address: &quot;789 main st, nashville&quot;
      }
    ]

but this returns

    [
      [],
      [%{address: &quot;123 main st, sacramento&quot;, name: &quot;joe&quot;}],
      [%{address: &quot;789 main st, nashville&quot;, name: &quot;sam&quot;}]
    ]

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/2Access中的一个。

以下是完成任务的一种可能方式。

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} -&gt; 
  Enum.any?(list_of_towns, &amp;String.contains?(address, &amp;1))
end)

#⇒ [
#   %{address: &quot;123 main st, sacramento&quot;, name: &quot;joe&quot;},
#   %{address: &quot;789 main st, nashville&quot;, name: &quot;sam&quot;}
# ]

Whether you are still after [ab]using a comprehension, use it as filter, not as another loop.

for person &lt;- people_details,
    List.last(String.split(person.address, &quot;, &quot;)) in list_of_towns,
  do: person           

#⇒ [
#   %{address: &quot;123 main st, sacramento&quot;, name: &quot;joe&quot;},
#   %{address: &quot;789 main st, nashville&quot;, name: &quot;sam&quot;}
# ]

答案2

得分: 1

&lt;!-- language-all: lang-elixir --&gt;

You can do this using a comprehension like this:

    for %{address: address} = person_detail &lt;- people_details,
        town &lt;- 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: &quot;123 main st, sacramento&quot;, name: &quot;joe&quot;},
      %{address: &quot;789 main st, nashville&quot;, name: &quot;sam&quot;}
    ]

However, I wouldn&#39;t write this code normally - the first part of Aleksei&#39;s answer is what I&#39;d write too.
英文:

<!-- language-all: lang-elixir -->

You can do this using a comprehension like this:

for %{address: address} = person_detail &lt;- people_details,
    town &lt;- 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: &quot;123 main st, sacramento&quot;, name: &quot;joe&quot;},
  %{address: &quot;789 main st, nashville&quot;, name: &quot;sam&quot;}
]

However, I wouldn't write this code normally - the first part of Aleksei's answer is what I'd write too.

huangapple
  • 本文由 发表于 2023年2月8日 12:06:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75381291.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定