How to replace the charactors in the string?

How to realize the following perl translating task in Julia?

#/user/bin/perl

my $string = ‘The cat sat on the mat’;
$string =~ tr/ao/oL/;
print “$string\n”;

#-------------------------
The cot sot Ln the mot

please use docs

https://docs.julialang.org/en/v1/base/strings/#Base.replace-Tuple{AbstractString,Pair}

2 Likes

which one ?

function tr(s::String,target::String,sub::String)
    return Base.replace(s,target => sub)
end

mystring = "The cat sat on the mat"
mystring = tr(mystring,"at","ot")
println(mystring)
$ julia zzz.jl
The cot sot on the mot

It doesn’t work properly. The request image means every character changes ( ‘a’ to ‘o’ and ‘o’ to ‘L’) independently against the original string.

julia> function g(s, tar, rep)
           @assert length(tar) == length(rep)
           replace(collect(s), Dict(zip(tar,rep))...) |> join
       end
g (generic function with 1 method)

julia> g("The cat sat on the mat", "ao", "oL")
"The cot sot Ln the mot"
2 Likes

Quite smart solution. :+1:

but it costs 0.335752 seconds for 100000 loops. In contrast, Perl costs only 0.015 seconds.

You never told us that performance is a requirement.

Also, how did you get those timings? Make sure that you don’t benchmark in global scope.

@time begin
end

in global scope 0.335752 seconds
only for loops (excluding definition of function) 0.199178 seconds

try this

# Implement Perl tr function
function perl_tr(s::AbstractString, target::AbstractString, rep::AbstractString)
    @assert length(target) == length(rep)
    Base.replace(collect(s), Dict(zip(target,rep))...) |> join
end

let
    mystring = "The cat sat on the mat"
    mystring = perl_tr(mystring,"ao","oL")
    println(mystring)
end

typecasting it to AbstractString could make it faster.

so, don’t to that!

This doesn’t type cast anything. Generally, explicit types in function signatures don’t matter for performance.

1 Like

pretty sure the cost is in zip and dict, maybe just do a for loop.

1 Like

This doesn’t type cast anything. Generally, explicit types in function signatures don’t matter for performance.

Doesn’t the compiler only generate code for AbstractString and for nothing else? So less code equals better performance.

No. It always specializes on the actual runtime types. Independent of the function signature. Explicit types only have the effect of a filter: don’t except anything but only subtypes of AbstractStrings.

1 Like

To be convenient for test, the Perl script attached here.

#!/usr/bin/perl
use strict;
use warnings;

my $i=100000;
my $start=times;
while ($i>1) {
my $string = ‘The cat sat on the mat’;
$string =~ tr/ao/oL/;
print “$string\n”;
$i–;
}
print times-$start," seconds\n";

You should comment out print “$string\n”; unless you want IO to be part of your benchmark.

can you please wrap your code with ``` for readability?

1 Like

I wonder why there is no multi-pair version of replace for strings. Anyways, the straightforward

function h(s)
        snew = replace(s, 'o'=>'L')
        return replace(snew, 'a'=>'o')
end

is already ~3x faster than the other Julia implementation in this thread:

using BenchmarkTools

function g(s, tar, rep)
           @assert length(tar) == length(rep)
           replace(collect(s), Dict(zip(tar,rep))...) |> join
end

function h(s)
        snew = replace(s, 'o'=>'L')
        return replace(snew, 'a'=>'o')
end

@btime g("The cat sat on the mat", "ao", "oL"); # 1.660 μs
@btime h("The cat sat on the mat"); # 527.368 ns

Running your perl script (after removing the print statements), I get: 15-31 ms which is much slower. I don’t know if the perl benchmark is any good (I don’t know how to properly benchmark in perl). But taking it for what it is, the Julia implementation h is more than 2500x faster.