# Replacing multiple strings errors

**URL:** <https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654>\
**Category:** General Usage\
**Created:** [August 18, 2018, 8:48am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654 "2018-08-18T08:48:30Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 18, 2018, 8:48am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/1 "2018-08-18T08:48:30Z")

</div>

Am I having a stroke or something? Is this not supposed to work (version 1.0):

```julia
julia> replace("ABC", "A"=>"a", "B"=>"b")
ERROR: MethodError: no method matching replace(::String, ::Pair{String,String}, ::Pair{String,String})
Closest candidates are:
  replace(::AbstractString, ::Pair, ::Pair) at set.jl:487
  replace(::Any, ::Pair...; count) at set.jl:428
  replace(::Union{Function, Type}, ::Pair, ::Pair; count) at set.jl:486
  ...
Stacktrace:
 [1] replace(::String, ::Pair{String,String}, ::Pair{String,String}) at ./set.jl:487
 [2] top-level scope at none:0

```

It works for vectors:

```julia
julia> replace([1,2,3], 2=>20, 3=>30)
3-element Array{Int64,1}:
  1
 20
 30

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 18, 2018, 9:01am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/2 "2018-08-18T09:01:08Z")

</div>

This is the code being called, which explicitly throws an error for this case (set.jl:487). But why?

```julia
replace(a::AbstractString, b::Pair, c::Pair) = throw(MethodError(replace, (a, b, c)))

```

Adding more replacement pairs also fails, but in a different way:

```julia
julia> replace("ABC", "A"=>"a", "B"=>"b", "C"=>"c")
ERROR: MethodError: no method matching similar(::String, ::Type{Any})
Closest candidates are:
  similar(::Array{T,1}, ::Type) where T at array.jl:329
  similar(::Array{T,2}, ::Type) where T at array.jl:330
  similar(::Array, ::Type, ::Tuple{Vararg{Int64,N}}) where N at array.jl:332
  ...
Stacktrace:
 [1] _similar_or_copy(::String, ::Type{Any}) at ./set.jl:321
 [2] #replace#232(::Nothing, ::Function, ::String, ::Pair{String,String}, ::Vararg{Pair{String,String},N} where N) at ./set.jl:431
 [3] replace(::String, ::Pair{String,String}, ::Pair{String,String}, ::Pair{String,String}) at ./set.jl:428
 [4] top-level scope at none:0

```

while this is no problem:

```julia
julia> replace([1,2,3], 1=>10, 2=>20, 3=>30)
3-element Array{Int64,1}:
 10
 20
 30

```

---

<div class="post-metadata">

**Author:** ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)\
**Post date:** [August 18, 2018, 9:36am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/3 "2018-08-18T09:36:18Z")

</div>

You can always do:

`join(replace(split("ABC", ""), "A"=>"a", "B"=>"b"))`

Strings being immutable might be the problem…?

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [August 18, 2018, 9:37am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/4 "2018-08-18T09:37:08Z")

</div>

I guess the design of `replace` for strings is to allow only one pattern because patterns in a string can overlap so it would be ambiguous in what sequence to apply them.  
But I have not implemented it so it is just a guess.

If you want to apply patterns sequentially you can do:

```
reduce(replace, ["A"=>"a", "B"=>"b", "C"=>"c"], init="ABC")

```

EDIT. Just to clarify what I mean by this ambiguity. The following codes do not produce identical results:

```julia
julia> reduce(replace, [1=>10, 10=>20], init=[1,2,3])
3-element Array{Int64,1}:
 20
  2
  3

julia> replace([1,2,3], 1=>10, 10=>20)
3-element Array{Int64,1}:
 10
  2
  3

```

because in `replace([1,2,3], 1=>10, 10=>20)` the patterns are not applied sequentially.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 18, 2018, 9:45am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/5 "2018-08-18T09:45:16Z")

</div>

I guess the error message could clarify this, then, because it seemed to me like something that should obviously work. Especially this:

```julia
ERROR: MethodError: no method matching replace(::String, ::Pair{String,String}, ::Pair{String,String})
Closest candidates are:
  replace(::AbstractString, ::Pair, ::Pair) at set.jl:487

```

made me think it was a bug.

I still don’t get what is ambiguous. Would it not just be understood as

- Iterate through string
- if original char == “A”: replace with “a”
- elseif original char == “B”: replace with “b”

So that `replace("ABC", "A"=>"B", "B"=>"A")` would return `"BAC".`

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 18, 2018, 9:47am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/6 "2018-08-18T09:47:10Z")

</div>

> [@bkamins](#):
>
> because in `replace([1,2,3], 1=>10, 10=>20)` the patterns are not applied sequentially.

Yes, I would expect the second pattern. That would even be consistent with your example here. Why would this not be the same for strings?

**Edit:** I mean, the behaviour for strings should be the same as for vectors.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 18, 2018, 9:53am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/7 "2018-08-18T09:53:13Z")

</div>

I guess it’s not ambiguous for single characters, but might be for longer string replacements:

```julia
 replace("ABC", "AB"=>"1", "BC"=>"2")

```

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [August 18, 2018, 9:55am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/8 "2018-08-18T09:55:50Z")

</div>

> [@DNF](#):
>
> I guess it’s not ambiguous for single characters, but might be for longer string replacements.

This is exactly what I mean.

In general I guess you could use the rule:

> always use the leftmost pattern that matches the earliest in the string and move forward in the source string as much as the pattern eats up and repeat the process.

which would be unambiguous but probably not easy to digest for a user (this problem is not present with arrays as you always substitute one element for one element).

And I agree that `replace(::AbstractString, ::Pair{<:AbstractChar}...)` can be safely defined and should be 100% clear. Currently we have only `replace(::AbstractString, ::Pair{<:AbstractChar})`.

I guess you could open an issue or PR to Julia for this clarification.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 18, 2018, 9:57am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/9 "2018-08-18T09:57:55Z")

</div>

I will at least open an issue regarding the documentation and error message. I still need to read up on how to contribute PRs.

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [August 18, 2018, 10:33am UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/10 "2018-08-18T10:33:23Z")

</div>

An issue is already opened, see [https://github.com/JuliaLang/julia/issues/25383](https://github.com/JuliaLang/julia/issues/25383).  
The primary reason why this doesn’t work is that it’s simply as yet unimplemented (multiple replacement in other collections with the pair API was implemented not so long ago), and IIRC the issue is that it’s not trivial to implement, cf. this open PR: [https://github.com/JuliaLang/julia/pull/25732](https://github.com/JuliaLang/julia/pull/25732) (and [https://github.com/JuliaLang/julia/pull/25396](https://github.com/JuliaLang/julia/pull/25396)).

---

<div class="post-metadata">

**Author:** ![11115](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/11115/32/7409_2.png) [@11115](https://discourse.julialang.org/u/11115)\
**Post date:** [March 13, 2019, 4:23pm UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/11 "2019-03-13T16:23:43Z")

</div>

Maybe you can use like this way  
replace(replace(“ABC”,“A”=\>“a”),“B”=\>“b”)

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 13, 2019, 5:22pm UTC](https://discourse.julialang.org/t/replacing-multiple-strings-errors/13654/12 "2019-03-13T17:22:24Z")

</div>

Welcome to the forum!

This is largely the same as the `reduce` solution suggested above. (Which by the way should probably not use `reduce` but `foldl`.)

Your suggestion is likely slightly more performant than `foldl`, but using `foldl` is more flexible since you can pass in an array with any number of replacement strings.

By the way, you should quote your code using triple backticks ``` for better readability and to prevent things like “smart quotes” that prevents your code from working as is.
