2016-08-09 42 views
1

Mit einer Karte von old_new Werten, was ist der idiomatische Weg, diese alten_value durch new_values ​​in einer Zeichenkette zu ersetzen?Wie man eine Liste der alten Werte durch neue in einer Zeichenkette ersetzt

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

Da Elixir unveränderlich ist, weiß ich nicht, wie man das macht.

Antwort

3

(. Ich gehe davon aus Ihrer Karte String Schlüssel hat, nicht Atome)

Wenn Sie mit der Ausführung des Ersatz eines nach dem anderen in Ordnung sind, können Sie einfach Enum.reduce mit String.replace verwenden:

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" 

Aber wenn Sie sie parallel ausführen möchten, für Leistung oder Korrektheit (die vorherige Lösung wird ein anderes Ergebnis geben, wenn einer der Schlüssel der Karte mit einem anderen Wert übereinstimmt), würde ich etwa :binary.compile_pattern, :binary.match, und verwenden Musteranpassung:

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) 

Ausgang:

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

was hat das '<< vor :: binary-Größe (Start), match :: binary-Größe (Länge), Rest :: binary >>' tun? – Johshi

+0

Es teilt den Wert der rechten Seite in 3 Binaries der Größen "start", "length" und was noch übrig ist, und ordnet sie 'before',' match' und 'rest' zu. – Dogbert

+0

aber was ist "<<" and ">>" und "::"? – Johshi