如何在 Elixir 中迭代和修改映射内的键值对。示例代码如下。我需要从任何地方删除 c:

how to iterate and modify key-value pair inside map in Elixir. Sample code is below. I need to remove c: from everywhere

** 下面是示例地图,其中有 c: 在一些键的开头,我想要相同的地图,但键中的任何地方都没有 **

map = %{
  "soap:Body" => {"c:replyMessage",
   %{
     "c:ccCaptureReply" => %{
       "c:amount" => "100.00",
       "c:reasonCode" => "100",
       "c:reconciliationID" => "2",
       "c:requestDateTime" => "2019-07-10T16:57:49Z"
     },
     "c:decision" => "ACCEPT",
     "c:merchantReferenceCode" => "1255",
     "c:purchaseTotals" => {"c:currency", "US"},
     "c:reasonCode" => "100",
     "c:requestID" => "2",
     "c:requestToken" => "FkKZy21",
     "xmlns:c" => "urn:schemas-cybersource-com:transaction-data-1.165"
   }},
  "soap:Header" => {"wsse:Security",
   %{
     "wsu:Timestamp" => %{
       "wsu:Created" => "2019-07-10T16:57:49.246Z",
       "wsu:Id" => "Timestamp-90787002",
       "xmlns:wsu" => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
     },
     "xmlns:wsse" => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
   }},
  "xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/"
} 

即使 核心支持深度遍历,您也有元组作为值并且元组不可迭代。

唯一的方法是编写基于模式匹配的递归解决方案。

defmodule Sanitizer do
  def yo(%{} = map) do
    map
    |> Enum.map(fn
      {<<"c:", rest::binary>>, v} -> {rest, yo(v)}
      {k, v} -> {k, yo(v)}
    end)
    |> Map.new()
  end
  def yo({<<"c:", rest::binary>>, v}), do: {rest, yo(v)}
  def yo({k, v}), do: {k, yo(v)}
  def yo(any), do: any
end

Sanitizer.yo(map)
#⇒ sanitized result

FWIW,在我认为拥有 leftpad 之类的库就足够好了的时候,我写了一个 Iteraptor 库。如果它没有元组(无论如何都无法遍历),它可以处理输入。