Stream: helpdesk (published)

Topic: ✔ replace character in a string


view this post on Zulip Leandro Martínez (Jun 13 2024 at 22:41):

What's the reasonable way to replace a character in a String in a specified position? Well, maybe replace is no possible safely, but is this the best we can get?

new = old[1:pos-1]*'C'*[pos+1:end]

Maybe with @views

view this post on Zulip Mason Protter (Jun 13 2024 at 23:53):

Accessors.jl has functionality for it:

julia> using Accessors

julia> @set "helio"[4] = 'l'
"hello"

view this post on Zulip Leandro Martínez (Jun 14 2024 at 00:15):

Nice, but it just seems to be doing the same I do (so not worth the dependency):

julia> s = "abcdefghijklmnop"
"abcdefghijklmnop"

julia> g(s) = @set s[10] = 'C'
g (generic function with 1 method)

julia> f(s) = s[1:9]*'C'*s[11:end]
f (generic function with 1 method)

julia> @b f(s)
85.958 ns (3.03 allocs: 104.664 bytes)

julia> @b g(s)
85.509 ns (3.02 allocs: 104.609 bytes)

view this post on Zulip Mason Protter (Jun 14 2024 at 01:51):

Yeah that’s not particularly surprising. I like Accessors because it lets people ‘share’ these sorts of implementations, and takes some of the guess work out of it.

that is, I wouldnt be surprised if there was a more efficient/safe way to do this, and I’d hope that if I used Accessors, someone might contribute that implementation.

view this post on Zulip Mason Protter (Jun 14 2024 at 01:52):

It’s also just cleaner syntax-wise

view this post on Zulip aplavin (Jun 14 2024 at 02:28):

Also, the Accessors solution works for multi-byte characters, unlike the code from the first post:

julia> old = "абвгд"

julia> pos = 5

julia> old[pos]
'в': Unicode U+0432 (category Ll: Letter, lowercase)

julia> old[1:pos-1]*'C'*old[pos+1:end]
ERROR: StringIndexError: invalid index [4], valid nearby indices [3]=>'б', [5]=>'в'
Stacktrace:
 [1] string_index_err(s::String, i::Int64)
   @ Base ./strings/string.jl:12
 [2] getindex(s::String, r::UnitRange{Int64})
   @ Base ./strings/string.jl:470
 [3] top-level scope
   @ REPL[21]:1

julia> @set old[pos] = 'C'
"абCгд"

view this post on Zulip aplavin (Jun 14 2024 at 02:29):

That's the implementation: https://github.com/JuliaObjects/Accessors.jl/blob/270e78fed32763096c448541148d520aa275e667/src/setindex.jl#L47.
May be upstreamed to Base if someone is up to making a PR, I guess...

view this post on Zulip Jakob Nybo Nissen (Jun 14 2024 at 05:07):

There probably isn't a better way than the f function, if it used views.
Or you can use StringViews.jl which are mutable

view this post on Zulip Notification Bot (Jun 14 2024 at 11:36):

Leandro Martínez has marked this topic as resolved.

view this post on Zulip Leandro Martínez (Jun 14 2024 at 11:37):

Thanks all for the alternatives and tips. My use case is simple enough so that I will just keep the simple function for now.


Last updated: Nov 06 2024 at 04:40 UTC