如果存在重复值,如何映射对象?

时间:2018-05-03 11:04:16

标签: arrays loops elixir

我有两个列表,list_a = [%{id: 1, name: "Jack"}, %{id: 2, name: "John}]list_b = [%{id: nil, name: "Jack"}]

我想要实现的是,通过比较两个列表,如果有重复的名称,请添加字段status: true,如果没有,请添加字段status: false

因此预期结果为combined_list = [%{id: 1, name: "Jack", status: true}, %{id: 2, name: "John, status: false}]

为了实现目标,我循环两个列表并合并结果。

list_status_true =
for object <- list_a do
  found =      
    Enum.find(
      list_b,
        fn(x) ->
          x.name == object.name 
        end
      )

  if !is_nil(found) do
    %{
      id: object.id,
      name: object.name,
      status: true
    }
  end 
end

list_status_false =
for object <- list_b do
  found =      
    Enum.find(
      list_a,
        fn(x) ->
          x.name == object.name 
        end
      )

  if is_nil(found) do
    %{
      id: object.id,
      name: object.name,
      status: false
    }
  end 
end

list_status_true ++ list_status_false

但我觉得这个功能可以简化..有什么建议吗?

2 个答案:

答案 0 :(得分:2)

我将所有姓名收集到MapSet中,然后循环浏览list_b一次,检查MapSet中是否存在该名称:

list_a = [%{id: 1, name: "Jack"}, %{id: 2, name: "John"}]
list_b = [%{id: nil, name: "Jack"}]

names = for x <- list_b, into: MapSet.new, do: x.name

IO.inspect for x <- list_a, do: Map.put(x, :status, x.name in names)

输出:

[%{id: 1, name: "Jack", status: true}, %{id: 2, name: "John", status: false}]

答案 1 :(得分:2)

与@Dogbert提供的几乎相同的解决方案,但没有理解:

list_a = [%{id: 1, name: "Jack"}, %{id: 2, name: "John"}]
list_b = [%{id: nil, name: "Jack"}]

names = list_b |> Enum.map(& &1.name) |> Enum.uniq
Enum.map(list_a, fn %{name: name} = e ->
  Map.put(e, :status, name in names)
end)
#⇒ [%{id: 1, name: "Jack", status: true},
#   %{id: 2, name: "John", status: false}]