You can use Regex.replace/3 to do the replacements in one go. This would be more efficient than @Adam's for + String.replace/3 solution, especially if there a large number of elements in data:
strings = [
"Hello %{name}, do you come from %{country} ?",
"Did %{name} just arrived from %{country} ?",
"Today, %{name} will go to %{country}",
"Today, %{name} will join us"
]
data = %{"name" => "Julio", "country" => "Nirvana"}
for string <- strings do
Regex.replace(~r/%{(\w+)}/, string, fn _, key -> Map.fetch!(data, key) end)
end
|> IO.inspect()
Output:
["Hello Julio, do you come from Nirvana ?",
"Did Julio just arrived from Nirvana ?",
"Today, Julio will go to Nirvana",
"Today, Julio will join us"]
The regex /%{(\w+)}/ matches %{ followed by one or more letters or numbers (\w+) followed by }, capturing the letter/number sequence, which we use in the second argument of the replacement callback to fetch the right replacement value from data.
One more difference compared to @Adam's solution is that this will raise an error if the string contains an interpolation that does not exist in data instead of silently ignoring it:
strings = ["Today, %{name} will go to %{city}"]
raises
** (KeyError) key "city" not found in: %{"country" => "Nirvana", "name" => "Julio"}
:erlang.map_get("city", %{"country" => "Nirvana", "name" => "Julio"})
(You can handle such errors in a different way if you want by changing what the replacement function does.)
String#%is not doing any sanitization for strings, which means for strings it’s an exact equivalent for interpolation. Would you mind to elaborate please?