in reply to The nth occurrence of a character

I'd've probably used something like:

sub nthPos { my $s= \shift @_; my( $p, $n )= @_; local( pos($$s) ); 0 while $$s =~ /\Q$p/g && 0 < --$n; return if 0 < $n; return 1+pos($$s); }

Which uses several things that I wouldn't actually use without testing first but that I don't feel like spoiling the mystique of to myself at this point and so I have not yet tested.

- tye        

Replies are listed 'Best First'.
Re^2: The nth occurrence of a character (simple /$c/g)
by BrowserUk (Patriarch) on Feb 09, 2006 at 09:06 UTC

    Go on, spoil the mystique :)

    Even fixing up the out-by-two error s/1+pos($$s)/pos($$s)-1/, I can't see how to correct the pos memory factor without explicitly resetting it? Which makes taking the reference and localising it redundant?

    #! perl -slw use strict; sub tye { my $s= \shift @_; my( $p, $n )= @_; local( pos($$s) ); 0 while $$s =~ /\Q$p/g && 0 < --$n; return if 0 < $n; return 1+pos($$s); } my $data = 'a' x 100; print "want: got"; printf "%3d : %3d\n", $_-1, tye( $data, 'a', $_ ) for 1 .. 30; __END__ C:\test>junk want: got 0 : 2 1 : 4 2 : 7 3 : 11 4 : 16 5 : 22 6 : 29 7 : 37 8 : 46 9 : 56 10 : 67 11 : 79 12 : 92 Use of uninitialized value in printf at C:\test\junk.pl line 16. 13 : 0 14 : 16 15 : 32 16 : 49 17 : 67 18 : 86 Use of uninitialized value in printf at C:\test\junk.pl line 16. 19 : 0 20 : 22 21 : 44 22 : 67 23 : 91 Use of uninitialized value in printf at C:\test\junk.pl line 16. 24 : 0 25 : 27 26 : 54 27 : 82 Use of uninitialized value in printf at C:\test\junk.pl line 16. 28 : 0 29 : 31

    About the best performing modification of it I came up with is:

    sub tyem { my( $s, $c, $n ) = @_; 0 while $s =~ /\Q$c/g && 0 < --$n; my $rv = pos( $s )-1; pos($s) = -1; return if 0 < $n; return $rv; }

    which doesn't fair so well, though it is still quicker than any of the other regex-based solutions.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      If you copy the string (and then destroy the copy), then it is a waste of time to set pos($s)= -1.

      It was not an off-by-two error as I consider returning -1 (a 'true' value) for 'not found' to rather suck as an interface, and prefer to avoid returning a false value (0) for 'found at 1st character' so I meant to return the position of the character as asked, not the offset to it.

      - tye