'How to replace a string using a wrapper function in Julia
I am trying to write a Julia function that performs a find and replace operation on each element in an array of strings using regular expressions. It is essentially a wrapper around a broadcasted replace() call. If you are familiar with R's stringr package, this function should more or less work the same as stringr::str_replace_all().
The code below replaces all instances of 'ee' with 'EE', replacing "greetings" with "grEEtings":
arr = ["hi", "hello", "welcome", "greetings"]
replace.(arr, r"e{2}" => "EE")
The function I wrote does not return modifications of the values in arr:
function str_replace_all(string::String, pattern::String, replacement::String)
replace.(string, Regex(pattern) => replacement)
end
str_replace_all(arr, "e{2}", "EE")
What went wrong? Thanks!
Solution 1:[1]
The code you provided does not yet run, since you are trying to pass a String, but your function expects an Array of Strings. You either have to:
Remove the type annotation of
string::Stringin the function definition, orvectorize your function when calling it, using the '.' syntax:
str_replace_all.(arr, "e{2}", "EE")
It should also be noted that your function will not replace strings in the array, it will create a new array containing the replaced values. If you want to get the replaced values in your array, you could do something like (Edit: as DNF noted in the comments, this way a new array is created and binded to the variable arr, which is not
really efficient):
function str_replace_all(string, pattern::String, replacement::String)
replace.(string, Regex(pattern) => replacement)
end
arr = str_replace_all(arr, "e{2}", "EE")
Solution 2:[2]
drop type annotations in your function and it should work:
julia> arr = ["hi", "hello", "welcome", "greetings"]
julia> function str_replace_all(string, pattern, replacement)
replace.(string, Regex(pattern) => replacement)
end
Solution 3:[3]
You have to actually modify the array:
function str_replace_all!(arr, pattern, replacement)
arr .= replace.(arr, pattern => replacement)
end
You should put a ! at the end of the function name to signal that it mutates the input. That is only a convention, it has no effect, but you should follow it nonetheless.
Solution 4:[4]
After incorporating feedback from everyone's answers, here is my solution:
function str_replace_all(string::String, pattern::String, replacement::String)
replace(string, pattern => replacement)
end
function str_replace_all(string::String, pattern::Regex, replacement::String)
replace(string, pattern => replacement)
end
It is best to take advantage of multiple dispatch to allow users to decide on the type of pattern to send to replace()--an exact match (string) or a regular expression. Further, vectorization of the solution should be done when calling the function (e.g. str_replace_all.()) instead of being placed inside the function's body (as was the case with the call to replace.() in the OP).
Ex:
arr = ["hi", "hello", "welcome", "greetings"]
str_replace_all.(arr, "ee", "EE")
str_replace_all.(arr, r"e{2}", "EE")
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | ???????? |
| Solution 3 | DNF |
| Solution 4 | Connor Krenzer |
