http://www.perlmonks.org?node_id=11104766

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"};

    Dave.

      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 (Archbishop) 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 (Monsignor) 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";
    Bill
      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)
        Bill
Re: Suggestion on rewriting small code
by rsFalse (Chaplain) 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.