Forum Moderators: coopster & phranque

Message Too Old, No Replies

Good ol' switch-case, what's a good alternative?

         

csdude55

4:11 am on Aug 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Well, I just learned that switch-case is now gone :'-(

I have a bunch of sections like:

if (
$str eq 'a' ||
$str eq 'b' ||
$str eq 'c' ||
... ||
$str eq 'z') {
# do whatever
}


In theory this is slow because it compares one at a time. In PHP I could use switch like this:

switch ($str) {
case 'a':
case 'b':
case 'c':
...
case 'z':
# do whatever
}


and it's (supposedly) a lot faster because the condition is only evaluated once and then the result is compared to each case.

Perl offers up the given-when alternative, but it evaluates the condition each time, too, so I doubt that it's any faster than the if() statement. And since it's listed as experimental, I'm not sure that it'll survive for long, either.

I see that there's a Switch module, but it doesn't say anything about chaining cases:

[metacpan.org...]

So what's a good alternative?

I know that I could do this and it would take less storage, but I doubt that a regex is faster to process:

if ($str =~ #^
a |
b |
c |
.. |
z
$#x) {
# do whatever
}


I WISH that this worked, but of course it doesn't:

if ($str eq 'a' || 'b' || 'c' || ... || 'z') {
# this reads like, "if $str equals 'a', or if 'b' exists"
# and since 'b' obviously exists, then it succeeds
}


Any other suggestions?

csdude55

5:12 am on Aug 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Sorry to reply to myself, but I did some bench testing and, surprise! I checked 3 formats, and the regex was the fastest!

These were over 10,000 iterations:

# 0.00917506217956543
if (
$str eq 'a' ||
...
$str eq 'z'
) { ... }

# 0.00747895240783691
if (
$str =~ m#^
a |
z
$#x) { ... }

# 0.0703740119934082
%arr = (
'a' => 1,
...
'b' => 1
);

if (exists($arr{$str})) { ... }


Changing the last one from if (exists($arr{$str})) to if ($arr{$str} == 1) made it 0.002 faster, but still far slower than the others.

I'm still open to other suggestions, but so far the regex is winning in terms of readability, size, AND speed!

NickMNS

5:42 am on Aug 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Let start by saying I know nothing about Perl, it's way too cryptic for my liking. But here some tricks I use in both Python and JS.
I some situation where you may want to use a switch statement you may also be able to use a mapping.

for example:

switch ($str) {
case 'a':
return 1
case 'b':
return 2
case 'c':
return 3
...
case 'z':
return 26


this could be replaced with:

ltr_to_num_map = {
"a": 1,
"b": 2,
"c": 3,
...
"z": 26,
}

ltr_to_num_map[$str] // when $str == a returns 1


Of course this doesn't work in all situations, but often enough.

Then for your example:
if ($str eq 'a' || 'b' || 'c' || ... || 'z') { ...do something } 


You can look for the inclusion of $str in an array:
in python:

if str in ['a','b','c', ... , 'z']:
...do something


or in JS:

if ( ['a','b','c', ... , 'z'].indexOf(str) >= 0) { ...do something }

Brett_Tabke

3:02 pm on Aug 21, 2021 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Ya, the regex library that Perl uses is highly optimized. Regex junkies really took Perl's to the next level. In almost all case a regex is going to be faster than a hand string or numeric comparison.

(and I have been slow (20 yrs) to warm up to regexs)

csdude55

5:22 pm on Aug 21, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



@NickMNS, Perl is actually my "first"! I learned Perl before I learned HTML, if you can believe that one. I don't use it anywhere near as much as I used to, though; I use PHP more than anything, so for the most part I just use Perl to update old scripts.

Perl is VERY powerful, though, so it's still a great language to know. And really, once you know Perl then everything else is easy :-D

Until they start taking away things like switch-case >:-(

@Brett_Tabke, I always used regex as a last resort, too, and when I bench test regex in PHP it's (almost) always the slowest! So I'm really surprised that it was the fastest here. I use switch a lot in PHP so now I'm nervous that it's going to be deprecated everywhere and I'll have to modify a million scripts.

But alright, I'm going to assume that regex is the bestest / fastest / easiest to maintainest, so I'll run with that unless someone suggests something better :-)