9

In Julia language, I want to use functions defined for Array{T,1} a.k.a. Vector{T} on a String, essentially treating it as Array{Char,1}.

An example of a function I would like to use:

julia> deleteat!("Hrello!",2)
ERROR: MethodError: no method matching deleteat!(::String, ::Int64)
Closest candidates are:
  deleteat!(::Array{T,1} where T, ::Integer) at array.jl:1177
  deleteat!(::Array{T,1} where T, ::Any) at array.jl:1214
  deleteat!(::BitArray{1}, ::Integer) at bitarray.jl:901
  ...
Stacktrace:
 [1] top-level scope at none:0

julia> deleteat!(['H','r','e','l','l','o','!'], 2)
6-element Array{Char,1}:
 'H'
 'e'
 'l'
 'l'
 'o'
 '!'

To be clear, I would like to start with a String and end up with a String, but use Array {Char,1} operations to alter the String.

1
  • That is a useful and well-illustrated question. Commented Dec 28, 2018 at 23:25

2 Answers 2

9

In Julia, one should always try collect firstly for getting a Vector from something else.

julia> deleteat!(collect("Hrello!"), 2)
6-element Array{Char,1}:
 'H'
 'e'
 'l'
 'l'
 'o'
 '!'
Sign up to request clarification or add additional context in comments.

4 Comments

You should probably mention that this is necessary because Strings are immutable.
collect is the way to go (and I would normally use it). One could also add that actually you could write Vector{Char}(str) and Vector{UInt8}(str) to convert it to a mutable collection of character or code units. If you need a collection of code units that is read only then one can use a codeunits function.
Good answer, but what is the inverse operation? I wasn't clear about this initially, but I want to end up with a String.
@dukereg join should do the job.
6

Strings can be split into Arrays and then operated on by using the split function.

For example, this could be done for your code above like this:

julia> deleteat!(split("Hrello!", ""), 2)
6-element Array{SubString{String},1}:
 "H"
 "e"
 "l"
 "l"
 "o"
 "!"

Edit

Since providing the above code example using split, I did the following benchmark comparison of collect vs. split for this problem.

The result is that collect is much faster (> 10X) than split as shown below.

julia> VERSION
v"1.0.3"

julia> using BenchmarkTools

julia> @benchmark deleteat!(split("Hrello!", ""), 2)
BenchmarkTools.Trial:
  memory estimate:  1.42 KiB
  allocs estimate:  26
  --------------
  minimum time:     748.396 ns (0.00% GC)
  median time:      804.819 ns (0.00% GC)
  mean time:        1.067 μs (20.80% GC)
  maximum time:     465.984 μs (99.71% GC)
  --------------
  samples:          10000
  evals/sample:     144

julia> @benchmark deleteat!(collect("Hrello!"), 2)
BenchmarkTools.Trial:
  memory estimate:  112 bytes
  allocs estimate:  1
  --------------
  minimum time:     60.299 ns (0.00% GC)
  median time:      65.431 ns (0.00% GC)
  mean time:        89.189 ns (20.99% GC)
  maximum time:     66.601 μs (99.83% GC)
  --------------
  samples:          10000
  evals/sample:     1000

@Gnimuc's advice to try collect first is definitely backed up by this benchmark.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.