2016-08-09 61 views
1

有一個old_new值的映射,在字符串中用new_values替換這些old_value的慣用方法是什麼?如何用一個字符串中的新值替換舊值的列表

my_map = %{"old_value1": "new_value1", "old_value2": "new_value2"} 
str = "some string .......old_value1 fafdsfd old_value2 faaaaaaa" 

由於藥劑是不可變的,我不知道該怎麼做。

回答

3

(我假設你的地圖有串鑰匙,而不是原子)

如果你的罰款由一個運行的替代品之一,你可以簡單地使用Enum.reduceString.replace

iex(1)> my_map = %{"old_value1" => "new_value1", "old_value2" => "new_value2"} 
%{"old_value1" => "new_value1", "old_value2" => "new_value2"} 
iex(2)> str = "some string .......old_value1 fafdsfd old_value2 faaaaaaa" 
"some string .......old_value1 fafdsfd old_value2 faaaaaaa" 
iex(3)> Enum.reduce(my_map, str, fn {old, new}, str -> String.replace(str, old, new) end) 
"some string .......new_value1 fafdsfd new_value2 faaaaaaa" 

但是,如果你想並行運行它們,爲了性能或者正確性(如果地圖上的任何鍵匹配任何其他值,以前的解決方案將給出不同的結果),我會使用類似:binary.compile_pattern,:binary.match和模式匹配:

defmodule Main do 
    def replace(string, map) do 
    replace(string, map, :binary.compile_pattern(Map.keys(map)), "") 
    end 

    defp replace(string, map, pattern, acc) do 
    case :binary.match(string, pattern) do 
     {start, length} -> 
     <<before::binary-size(start), match::binary-size(length), rest::binary>> = string 
     replacement = map[match] 
     replace(rest, map, pattern, acc <> before <> replacement) 
     :nomatch -> 
     acc <> string 
    end 
    end 
end 

my_map = %{"old_value1" => "new_value1", "old_value2" => "new_value2"} 
str = "some string .......old_value1 fafdsfd old_value2 faaaaaaa" 
IO.puts Main.replace(str, my_map) 

輸出:

some string .......new_value1 fafdsfd new_value2 faaaaaaa 
+0

是什麼'<<前::二進制大小(開始),匹配::二進制尺寸(長度),其餘::二進制>>'怎麼辦? – Johshi

+0

它將右手邊的值分割成3個大小爲'start','length'和剩下的大小的二進制文件,並將它們分別分配給''before','match'和'rest'。 – Dogbert

+0

但什麼是「<<" and ">>」和「::」? – Johshi

相關問題