Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re: split string using optimized code or perl one liner

by johngg (Canon)
on Feb 22, 2017 at 15:09 UTC ( [id://1182536] : note . print w/replies, xml ) Need Help??


in reply to split string using optimized code or perl one liner

Another way using pop rather than reverse.

johngg@shiraz:~/perl/Monks > perl -Mstrict -Mwarnings -E ' say join q{.}, sub { map { pop } 1 .. @_ }-> ( split m{\.}, shift );' www.perlmonks.org.split.reduce.code.check check.code.reduce.split.org.perlmonks.www

Update: Golfing this a bit still can't match davido's solution.

echo www.perlmonks.org.split.reduce.code.check | perl -lnE 'say sub{ma +p pop,@_}->(split/(\.)/)'

Cheers,

JohnGG

Replies are listed 'Best First'.
Re^2: split string using optimized code or perl one liner
by davido (Cardinal) on Feb 23, 2017 at 22:56 UTC

    The race is on....

    This shaves two strokes off my previous version.

    # -2 strokes: echo www.perlmonks.org.split.reduce.code.check |perl -lF'(\.)' -E'say +reverse@F' # Compare to: echo www.perlmonks.org.split.reduce.code.check |perl -lnE'say reverse +split/(\.)/'

    -F'pattern' sets -a auto-split mode with the pattern specified. The auto-split goes into @F. The -F field also sets -n automatically. So the original version and this version work essentially the same way, just relying on different ways to specify the split.


    Dave

      On that basis the following should work but it doesn't ...

      $ echo www.perlmonks.org.split.reduce.code.check | perl -lF'(\.)' -E's +ay sub{map pop,@_}->(@F)' $

      ... and I can't think why at the moment. Perhaps I'm misunderstanding what you have done :-/

      Cheers,

      JohnGG

        People are likely to get mixed results here. I assume it's because of this line in perlsyn: "If any part of LIST is an array, foreach will get very confused if you add or remove elements within the loop body, for example with splice. So don't do that."

        Why is this applicable?

        Let's simplify your construct a bit. my @O = sub {map pop, @_}->(@F) is very similar to my @O = map pop @F, @F, and that is quite similar to:

        my @O foreach (@F) { push @O, pop @F; }

        And the same rule applies, if you fiddle with the number of elements in the array Perl may get confused, or in other words "undefined behavior". The issue is that in both cases (map, or foreach), the list's size is evaluated up front before entering the loop, and that count probably remains fixed even if the size of the container you are iterating over shrinks. Then as you iterate, $_ is aliased to an element in the array. If the array shrinks, what does $_ alias to?

        Your code never looks at $_, instead just relying on the fact that before entering the loop Perl decides how many times to iterate. The fact that it works for some Perl versions is somewhat good luck, and luck is not reliable.


        Dave

        It works for me (Linux):

        $ echo www.perlmonks.org.split.reduce.code.check | \ perl -lF'(\.)' -E'say sub{map pop,@_}->(@F)' check.code.reduce.split.org.perlmonks.www