在 Elixir 中转换地图列表

Transform a list of maps in Elixir

我有一个地图列表,我通过查询 database.It 获得了一个日期时间字段,我想将其转换为另一个地图列表,其中日期时间字段被转换为其对应的纪元值。

我有:

[
  %{
    m_id: 267,
    end: #DateTime<2020-03-07 17:30:00Z>,
    start: #DateTime<2020-03-07 14:30:00Z>,
    type: "normal",
    s_name: "smum",
    w_id: 256
  },
  %{
    m_id: 267,
    end: #DateTime<2020-03-07 07:30:00Z>,
    start: #DateTime<2020-03-07 04:30:00Z>,
    type: "normal",
    s_name: "smum",
    w_id: 256
  }
]

我想将其转换为:

[
  %{
    m_id: 267,
    end: 12356789, #some epoch value for eg
    start: 12367576, #some epoch value for eg
    type: "normal",
    s_name: "smum",
    w_id: 256
  },
  %{
    m_id: 267,
    end: 12334567, #some epoch value for eg
    start: 12354767, #some epoch value for eg
    type: "normal",
    s_name: "smum",
    w_id: 256
  }
]

要转换单个地图,您可以执行

%{map | end: DateTime.to_unix(map.end), start: DateTime.to_unix(map.start) }

因此只需 Enum.map 遍历列表即可将其应用于所有列表成员:

Enum.map(list, fn map -> %{map | end: DateTime.to_unix(map.end), start: DateTime.to_unix(map.start) } end)

(我怀疑这里使用地图更新语法可能有问题,因为 end 是一个保留字,但我在 https://www.jdoodle.com/execute-elixir-online/ 中测试并且有效。)

我会 Kernel.SpecialForms.for/1 理解。

for %{start: s, end: e} = map <- list do
  %{map | start: DateTime.to_unix(s), end: DateTime.to_unix(e)}
end

它与 Enum.map/2 解决方案略有不同,因为它会丢弃那些 而不是 具有 startend 键的元素。要正确处理这些问题,应该明智地使用 Map.update/4