http://qs321.pair.com?node_id=1182522

madtoperl has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,
I am trying to reverse a string based on dot symbol and print the result. Below code is working fine. Do we have more efficient way of reducing the lines of code. Probably an one liner, please share your thoughts/a better version of code..
#!/usr/bin/perl use strict; use warnings; my $string = 'www.perlmonks.org.split.reduce.code.check'; my @array = (); @array = split /\./, $string; @array = reverse @array; print "Reversed data ==> @array\n";
Regards
madtoperl

Replies are listed 'Best First'.
Re: split string using optimized code or perl one liner
by toolic (Bishop) on Feb 22, 2017 at 13:48 UTC
    Two fewer lines:
    use strict; use warnings; my $string = 'www.perlmonks.org.split.reduce.code.check'; my @array = reverse split /\./, $string; print "Reversed data ==> @array\n";
Re: split string using optimized code or perl one liner (updated)
by haukex (Archbishop) on Feb 22, 2017 at 14:11 UTC

    Hi madtoperl,

    A oneliner you say?

    $ echo abc.def.ghi.jkl.mno | \ perl -lne 'print join ".", reverse split /\./' mno.jkl.ghi.def.abc

    Update: Golfed a tiny bit. If your shell causes you trouble with the backslash, try -F"[.]" instead.

    $ echo abc.def.ghi.jkl.mno | \ perl -F'\.' -lpe'$_=join".",reverse@F' mno.jkl.ghi.def.abc

    Documentation of the switches is in perlrun.

    Regards,
    -- Hauke D

Re: split string using optimized code or perl one liner
by Eily (Monsignor) on Feb 22, 2017 at 14:03 UTC

    Is it about efficiency or number of lines? In the first case, you'll have to Benchmark a bunch of solutions. Otherwise, TIMTOWTDI.

    $string = 'www.perlmonks.org.split.reduce.code.check'; print join " ", reverse( $string =~ /(\w+)/g); $, = " "; print reverse (split /[.]/, $string); my $out; $out = "$_ $out" for split /[.]/, $string; # Extra space at the end th +ough print $out;

Re: split string using optimized code or perl one liner
by davido (Cardinal) on Feb 22, 2017 at 16:05 UTC

    If efficiency is defined by keystrokes, you may save a few by using capturing parens in your split. You may also rely on the fact that the -n flag loads one line at a time into $_, and that split looks at $_ if no other string param is provided:

    echo www.perlmonks.org.split.reduce.code.check |perl -lnE 'say reverse + split /(\.)/'

    So this is 36 keystrokes if you start counting after the pipe. Someone will probably beat it though. One way to beat it will be eliminating two unneeded whitespace characters, so this gets it down to 34:

    echo www.perlmonks.org.split.reduce.code.check |perl -lnE'say reverse +split/(\.)/'

    If efficiency is defined by some other metric, you would probably need to benchmark a few alternatives according to that metric to determine which one wins.


    Dave

Re: split string using optimized code or perl one liner
by johngg (Canon) on Feb 22, 2017 at 15:09 UTC

    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

      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