Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^3: How to remove everything after last occurrence of a string?

by AnomalousMonk (Archbishop)
on Jun 07, 2022 at 22:41 UTC ( [id://11144494]=note: print w/replies, xml ) Need Help??


in reply to Re^2: How to remove everything after last occurrence of a string?
in thread How to remove everything after last occurrence of a string?

Do you still want to go with a regex solution? :-)

No | Yes, because (in this case at least) the rindex solution is wrong.

How can one say any result is incorrect if the OPer has specified no clear set of requirements for results? I admit this is tricky, but one can say the use of s/// in the OPed example code implies that the string operand should be unchanged if no version substring match is found. _rindex() in the code here fails to do this.

It's easy enough to define an rindex-based function that handles the no-match case (and it might even be a bit faster). But the argument seems to be that one should avoid using and learning about regexes because they are a bit arcane (indeed, regexes are the most counter-intuitive programming construct I know) and may vary a bit from language to language. This argument can be extended to languages themselves: We should not use Perl because it's not Python; not use Python because it's not C++; not use C++ because it's not...

To answer a use-case such as that described in the OP, I tend to reach first for a regex solution because it most clearly represents and achieves the required operation, not because it is the fastest (although sometimes it is). Implementing the required operation in terms of index/rindex, substr, etc., is possible, but may have its own pitfalls and drawbacks in terms of basic correctness, readability and maintainability.

These are all my own very personal preferences; others may differ.

Win8 Strawberry 5.30.3.1 (64) Tue 06/07/2022 17:48:45 C:\@Work\Perl\monks >perl use 5.010; use strict; use warnings; use constant { PATH => 0, VERSION => 1, WANT => 2, }; use Benchmark 'cmpthese'; use Test::More; my @tests = ( # version found [qw{ /a/b/version1/c/d version1 /a/b/version1 }], # version found [qw{ /some/path/3.5.2+tcl-tk-8.5.18+sqlite-3.10.0/a/b/c 3.5.2+tcl-tk-8.5.18+sqlite-3.10.0 /some/path/3.5.2+tcl-tk-8.5.18+sqlite-3.10.0 }], # version not found - no change in path [qw{ /some/path/3.5.2+tcl-tk-8.5.18+sqlite-3.10.0/a/b/c 9.9.9 /some/path/3.5.2+tcl-tk-8.5.18+sqlite-3.10.0/a/b/c }], ); plan tests => 2*@tests; for my $test (@tests) { is _regex (@$test[PATH, VERSION]), $test->[WANT]; is _rindex(@$test[PATH, VERSION]), $test->[WANT]; } cmpthese 0 => { regex0 => sub { _regex (@{$tests[0]}[PATH, VERSION]); }, regex1 => sub { _regex (@{$tests[1]}[PATH, VERSION]); }, regex2 => sub { _regex (@{$tests[2]}[PATH, VERSION]); }, rindex0 => sub { _rindex (@{$tests[0]}[PATH, VERSION]); }, rindex1 => sub { _rindex (@{$tests[1]}[PATH, VERSION]); }, rindex2 => sub { _rindex (@{$tests[2]}[PATH, VERSION]); }, }; sub _regex { my ($path, $version) = @_; $path =~ s/.*\Q$version\E\K.*//s; return $path; } my $r_offset; # variable creation excluded from timing sub _rindex { my ($path, $version) = @_; return ($r_offset = rindex $path, $version) >= 0 ? substr $path, 0, $r_offset + length $version : $path # version not found: return path unchanged ; } # sub _rindex { # my ($path, $version) = @_; # # return $path unless ($r_offset = rindex $path, $version) >= 0; # return substr $path, 0, $r_offset + length $version; # # } # sub _rindex { # fails if version not found # my ($path, $version) = @_; # # $path = substr $path, 0, length($version) + rindex $path, $versi +on; # # return $path; # } ^Z 1..6 ok 1 ok 2 ok 3 ok 4 ok 5 ok 6 Rate regex1 regex0 regex2 rindex1 rindex0 rindex2 regex1 104916/s -- -5% -52% -83% -84% -88% regex0 109922/s 5% -- -49% -82% -83% -88% regex2 217207/s 107% 98% -- -64% -66% -76% rindex1 602123/s 474% 448% 177% -- -6% -33% rindex0 641287/s 511% 483% 195% 7% -- -29% rindex2 899759/s 758% 719% 314% 49% 40% --

Update: Rats... Trashed the thrust of the entire post by getting the very first word wrong. Oh, well...


Give a man a fish:  <%-{-{-{-<

Replies are listed 'Best First'.
Re^4: How to remove everything after last occurrence of a string?
by GrandFather (Saint) on Jun 07, 2022 at 23:45 UTC

    It comes down to choosing the right tool for the task at hand. That is an art in itself. Often a regex is the right tool to solve a tricky matching problem. Sometimes something like index is the tool to use for a simple matching problem or where speed is critical. My main point is that raw execution speed should not be the first consideration when choosing tools to solve a problem. Demonstrable correctness and maintainability should come first and often go hand in hand. At this point the discussion doesn't have much to do with the OP or the specific implementation of any reply.

    My reply was addressing what could be seen as a "speed first" approach to coding being advocated by kcott's reply. Ken is an experienced coder so he can skip a few iterations ahead to get a solution that is both clean and quick. That is something that comes with experience, often bitter, so I thought a heads up for the less experienced was in order.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      Demonstrable correctness and maintainability should come first ... My reply was addressing what could be seen as a "speed first" approach to coding being advocated

      Strongly agree! See: on Code Optimization

      Sadly, there seems to have been an increase lately in monks asking for faster code without explaining why speed matters for their problem and without providing a benchmark. Some reacted appallingly on being given your well-meaning advice, one even deleting all his content and leaving the monastery in a huff.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11144494]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2024-04-19 07:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found