swapping values

220 Views Asked by At

I was wondering if there is an easy/clean way of swapping values as follows, perhaps using a single regex/substitution?

If $a ends with "x", substitute it with "y". And similarly if $a ends with "y", swap it with "x":

$a = "test_x";

if ($a =~ /x$/) {
  $a =~ s/x$/y/;
} else {
  $a =~ s/y$/x/;
}

I can only think of something like this:

$a = $a =~ /x$/ ? s/x$/y/ : s/y$/x/;
3

There are 3 best solutions below

0
On BEST ANSWER

This is simply:

$a =~ s/x$/y/ or $a =~ s/y$/x/;

It's almost always redundant to do a match to see if you should do a substitution.

Another way:

substr($a,-1) =~ y/xy/yx/;
1
On

You can squeeze it in a line like you show, perhaps a bit nicer with /r (with v5.14+).

Or you can prepare a hash. This also relieves the code from hard-coding particular characters.

my %swap = (x => 'y', y => 'x', a => 'b', b => 'a');  # expand as needed

my @test = map { 'test_' . $_ } qw(x y a b Z);

for my $string (@test)
{
    $string =~ s| (.)$ | $swap{$1} // $1 |ex;

    say $string;
}

The // (defined-or) is there to handle the case where the last character isn't in the hash, in which case $swap{$1} returns undef. Thanks to user52889 for the comment.

3
On

To swap individual characters, you can use tr///.

Not sure what your criteria for cleanliness or ease, but you could even do this inside the right hand side of the substitution:

$xy = "test_x" =~ s`([xy])$`$1=~tr/xy/yx/r`re; # $xy is "test_y"