Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Suggestion on rewriting small code

by ovedpo15 (Monk)
on Aug 21, 2019 at 06:52 UTC ( #11104766=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks, small question if you may. I have an array of numbers and I want to create a string in the following format:
"job==<number> || job==<number> || ... || job==<number>"
My try:
my @arr = (12341,1245125,1525125,125125125); my $str; # should be: "job==12341 || job==1245125 || job==1525125 || j +ob==125125125" my $flag = 1; my $counter = 0; foreach my $num (@arr) { $flag = 0 if($counter == scalar(@arr) - 1); $str .= "\"" if($counter == 0); $str .= "job==".$num; $str .= " || " if($flag); $str .= "\"" if($counter == scalar(@arr) - 1); $counter++; } print $str."\n";
It is a bit messy and I belive there is a better way to achive it. Also, in my final string, notice it contains "" in it (i'll added checks - if its in the first iteration or last iteration, add ".
I'm sure that there is a better way to do this. Is it possible to see some suggestions?

Replies are listed 'Best First'.
Re: Suggestion on rewriting small code
by dave_the_m (Monsignor) on Aug 21, 2019 at 07:01 UTC
    A more perlish way of doing it:
    my @arr = (12341,1245125,1525125,125125125); my $str = join ' || ', map "job==$_", @arr; $str = qq{"$str"};


      Yet one more variation to put it in a single line. But this is getting obfuscated :)

      my $str = do {local$"=" || ";qq{"@{[map{qq{job==$_}}@arr]}"}};

      Enjoy, Have FUN! H.Merijn
      A more perlish way of doing it: 
      my $str = join ' || ', map "job==$_", @arr;
      $str = qq{"$str"};

      # TIMTOWTDI:
      my $str = join '', '"', (join ' || ', map { "job==$_" } @arr), '"';
        One more way for those who likes to join:
        my $str = join ~~( join q[ || ], map { "job==$_" } @arr ), ( q["] ) x +2;
Re: Suggestion on rewriting small code
by GrandFather (Saint) on Aug 21, 2019 at 07:38 UTC

    Note that your print could be written:

    print "$str\n";

    or with current versions of Perl:

    say $str;
    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
Re: Suggestion on rewriting small code
by AnomalousMonk (Bishop) on Aug 21, 2019 at 15:00 UTC

    Normally I don't like to mess around with special variables (see perlvar) this way, but this is too neat:

    c:\@Work\Perl\monks>perl my @arr = (12341,1245125,1525125,125125125); my $str = do { local $" = ' || job=='; "job==@arr"; }; $" eq ' ' or die 'localization failed'; $str eq 'job==12341 || job==1245125 || job==1525125 || job==125125125' or die 'nope'; print ">$str< ok"; __END__ >job==12341 || job==1245125 || job==1525125 || job==125125125< ok

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

Re: Suggestion on rewriting small code
by BillKSmith (Prior) on Aug 21, 2019 at 10:55 UTC
    Try sprintf.
    use strict; use warnings; my @arr = (12341,1245125,1525125,125125125); my $str = sprintf 'job==%d || 'x(@arr-1) . 'job==%d', @arr; print "$str\n";
      my $str = sprintf 'job==%d || 'x(@arr-1) . 'job==%d', @arr;

      ++ your solution, but just a minor point of curiosity: why use  @arr-1 instead of  $#arr here?

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

        I have adopted the convention of using $#... when I actually mean "index of the last element" and @... when I mean a "count" of elements. A very small advantage is that this does not depend on the default value of "$[". (I have not used that in since I got over my FORTRAN habits years ago)
Re: Suggestion on rewriting small code
by rsFalse (Hermit) on Aug 21, 2019 at 08:08 UTC
    One more way:
    my $str = "(12341,1245125,1525125,125125125)"; print $str =~ s/,/ || /gr =~ y/()/"/r =~ s/(?=\b\d)/job==/gr;
Re: Suggestion on rewriting small code
by Anonymous Monk on Aug 21, 2019 at 10:03 UTC
    There is no need for flags and counters. It's just making it too complicated. Here is a simple way to do it. First initialize the string to a quote, because you want to start with a quote. then foreach number, add on a job string with the pipes after. once yore done, chop off the last three characters because you don't want two pipes and a space on the end. and put everything in a subroutine so that you aren't just using global variables all over the place.
    #!/usr/bin/env perl use strict; use warnings; use feature 'say'; run(); sub run { my @arr = (12341,1245125,1525125,125125125); my $str = '"'; foreach my $num (@arr) { $str .= "job==$num || "; } chop $str; chop $str; chop $str; $str .= '"'; say $str; return $str; }
      No you're making it too complicated! :-)

      The first problem is initializing the string with that quote.

      That causes the next, of concat in a loop, leaving crud at the end of the string.

      The dominoes continue to fall as ya chop chop chop away the first two mistakes.

      Finally, having to add a quote to the end of a sting is a bad sign that something went wrong earlier, which is now being hacked into compliance.

      Also you should know that printing from inside subs is a bad habit, but don't ask me how I know. It just quickly leads to layers of confusion. May I suggest:

      say run(); sub run { my @arr = (12341,1245125,1525125,125125125); my $str = join '', '"', (join ' || ', map {"job==$_"} @arr), '"'; return $str }
Re: Suggestion on rewriting small code
by Anonymous Monk on Aug 23, 2019 at 00:18 UTC
    If you ask a bunch of Perl programmers (with time on their hands) to demonstrate "Tim Toady" to you, you'll never get any work done. Just write the damned thing any which way that works then save the file and move on. Don't look back. Microseconds are plentiful these days.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11104766]
Approved by Athanasius
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2021-01-24 19:42 GMT
Find Nodes?
    Voting Booth?