我是Elixir的新手和一般的函数式编程。我想要的是更新地图中特定键的值,然后将该地图与另一个地图合并。
这是我的初始地图:
%{
"_id" => "exampleaaaaaaaaaaaaaaaaaaaaaaaaa",
"event" => "click",
"ip" => "127.0.0.1",
"location" => %{
"city" => "Oklahoma City",
"country" => "United States",
"country_short" => "US",
"latitude" => 35.4675598145,
"longitude" => -97.5164337158,
"postal_code" => "73101",
"region" => "Oklahoma",
"timezone" => "-05:00"
},
"msg" => %{
"_id" => "exampleaaaaaaaaaaaaaaaaaaaaaaaaa",
"_version" => "exampleaaaaaaaaaaaaaaa",
"clicks" => [%{"ts" => 1365111111, "url" => "http://mandrill.com"}],
"email" => "example.webhook@mandrillapp.com",
"metadata" => %{"user_id" => 111},
"opens" => [%{"ts" => 1365111111}],
"sender" => "example.sender@mandrillapp.com",
"state" => "sent",
"subject" => "This an example webhook message",
"tags" => ["webhook-example"],
"ts" => 1365109999
},
"ts" => 1519061856,
"url" => "http://mandrill.com",
"user_agent" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.8) Gecko/20100317 Postbox/1.1.3",
"user_agent_parsed" => %{
"mobile" => false,
"os_company" => "Apple Computer, Inc.",
"os_company_url" => "http://www.apple.com/",
"os_family" => "OS X",
"os_icon" => "http://cdn.mandrill.com/img/email-client-icons/macosx.png",
"os_name" => "OS X 10.6 Snow Leopard",
"os_url" => "http://www.apple.com/osx/",
"type" => "Email Client",
"ua_company" => "Postbox, Inc.",
"ua_company_url" => "http://www.postbox-inc.com/",
"ua_family" => "Postbox",
"ua_icon" => "http://cdn.mandrill.com/img/email-client-icons/postbox.png",
"ua_name" => "Postbox 1.1.3",
"ua_url" => "http://www.postbox-inc.com/",
"ua_version" => "1.1.3"
}
}
我有这个代码可以正常工作:
merge_maps = get_in_attempt(
payload, ["msg", "clicks"]
) ++ get_in_attempt(
payload, ["msg", "opens"]
)
main_map = %{
"ip" => get_in(payload, ["ip"]),
"city" => get_in(payload, ["location", "city"]),
"user_agent" => get_in(payload, ["user_agent"]),
"event_type" => get_in(payload, ["event"])
}
new_maps = Enum.map(merge_maps, fn elem ->
Map.update!(elem, "ts", &DateTime.from_unix!/1)
end)
|> Enum.map(fn elem ->
Map.merge(elem, main_map)
end)
new_maps
的输出:
[
%{
"city" => "Oklahoma City",
"event_type" => "click",
"ip" => "127.0.0.1",
"ts" => #DateTime<2013-04-04 21:31:51Z>,
"url" => "http://mandrill.com",
"user_agent" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.8) Gecko/20100317 Postbox/1.1.3"
},
%{
"city" => "Oklahoma City",
"event_type" => "click",
"ip" => "127.0.0.1",
"ts" => #DateTime<2013-04-04 21:31:51Z>,
"user_agent" => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.8) Gecko/20100317 Postbox/1.1.3"
}
]
我觉得在地图列表中列举两次是一种矫枉过正,但也许这是一个很好的&#34;考虑到函数式编程的不变性方面,实现它的方法。
这是&#34;最佳做法&#34;?
答案 0 :(得分:1)
我觉得在地图列表中枚举两次是不合理的
您可以合并两个Enum.map/2
调用,如下所示:
new_maps = Enum.map(merge_maps, fn elem ->
elem
|> Map.update!("ts", &DateTime.from_unix!/1)
|> Map.merge(main_map)
end)
除此之外,代码对我来说很好。