创建地图时创建列表列表

时间:2017-09-12 12:29:36

标签: elixir

我写了

let strLat : String = "23.035007"
let strLong : String = "72.529324"

let strLat1 : String = "23.033331"
let strLong2 : String = "72.524510"

override func viewDidLoad() {
        super.viewDidLoad()
        if (UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!)) {
            UIApplication.shared.openURL(URL(string:"comgooglemaps://?saddr=\(strLat),\(strLong)&daddr=\(strLat1),\(strLong2)&directionsmode=driving&zoom=14&views=traffic")!)
        }
        else {
            print("Can't use comgooglemaps://");
        }
    }

列表如下所示

Enum.reduce(list, map, fn elem, map ->
  key=hd(elem)
  Map.put(map, key, List.wrap(Map.get(map, key)) ++ tl(elem))
end)

,所需的结果如下所示

['B2', ['B1', 'B2', 'B3']],
['B2', ['A1', 'A2', 'A3']],

上面的代码确实产生了这个结果,但感觉非常难看。

我认为B2 => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']] 可以用于更好的变体,但似乎我无法同时掌握这些价值观。我试过了

Enum.into

但这并没有产生任何有用的东西。我相信我的大脑很难摆脱我在编码的最后四分之一世纪中使用的命令性思维。

3 个答案:

答案 0 :(得分:0)

我也使用Enum.reduce/3,但我使用的不是Map.put/3 + List.wrap/1,而是Map.update/4而不是hd/1tl/1一些模式匹配。

list = [
  ['A2', ['B1', 'B2', 'B3']],
  ['A2', ['A1', 'A2', 'A3']],
  ['B2', ['B1', 'B2', 'B3']],
  ['B2', ['A1', 'A2', 'A3']],
]

list
|> Enum.reduce(%{}, fn [k | v], acc ->
  Map.update(acc, k, v, &(&1 ++ v))
end)
|> IO.inspect

输出:

%{'A2' => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']],
  'B2' => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']]}

答案 1 :(得分:0)

虽然Enum.reduce/3完全没问题,但我会使用Enum.group_by/2来澄清意图。 (如果且只有表现不是最优先考虑的事项:reduce会快得多。)

list = [
  ['A2', ['B1', 'B2', 'B3']],
  ['A2', ['A1', 'A2', 'A3']],
  ['B2', ['B1', 'B2', 'B3']],
  ['B2', ['A1', 'A2', 'A3']],
] # thanks @Dogbert for the input

list
|> Enum.group_by(&Kernel.hd/1)
|> Enum.into(%{}, fn {k, e} ->
  {k, Enum.map(e, &List.last/1)}
end)

# %{'A2' => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']],
#   'B2' => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']]}

答案 2 :(得分:0)

在Dogbert的答案和blog post上大量建立我已经创建了自己的结构:

defmodule MyStruct do
  defstruct []
  def fetch(map, key), do: :maps.find(key, map)
end

defimpl Collectable, for: MyStruct do
  def into(original) do
    {original, fn
      source, {:cont, [k | v ]} -> Map.update(source, k, v, &(&1 ++ v))
      source, :done -> source
    end}
  end
end

现在我可以做到

defmodule MyModule
  map=Enum.into(list, %MyStruct{})
end

或在理解中使用into: %MyStruct{}