Print a separator between each iteration of a foreach loop

Discussion in 'Perl Misc' started by ShaunJ, Apr 15, 2008.

  1. ShaunJ

    ShaunJ Guest

    I want to print a separator between each iteration of a foreach loop,
    but not after the last element. How do I avoid printing the last
    extraneous comma in the following code snippet?

    foreach (@ARGV) {
    print $_, ',';
    }
    print "\n";

    In this simple example join ',' would suffice, but the real body of
    the foreach loop is more complicated. What I want to do is something
    like this:

    foreach (@ARGV) {
    print $_;
    print ',' unless last_element;
    }
    print "\n";

    Thanks,
    Shaun
     
    ShaunJ, Apr 15, 2008
    #1
    1. Advertising

  2. ShaunJ <> wrote:
    >I want to print a separator between each iteration of a foreach loop,
    >but not after the last element.


    That's a standard problem in CS. You need to process the first or last
    element outside the loop.

    > How do I avoid printing the last
    >extraneous comma in the following code snippet?
    >[...] What I want to do is something like this:
    >
    >foreach (@ARGV) {
    > print $_;
    > print ',' unless last_element;
    >}
    >print "\n";


    print $ARGV[0]; shift @ARGV
    for (@ARGV) {
    print ',';
    print $_;
    }

    OR

    for (@ARGV[0..@ARGV-2]) {
    print $_;
    print ',';
    }
    print $ARGV[$#ARGV];

    jue
     
    Jürgen Exner, Apr 15, 2008
    #2
    1. Advertising

  3. ShaunJ

    Guest

    ShaunJ <> wrote:
    > I want to print a separator between each iteration of a foreach loop,
    > but not after the last element. How do I avoid printing the last
    > extraneous comma in the following code snippet?
    >
    > foreach (@ARGV) {
    > print $_, ',';
    > }
    > print "\n";
    >
    > In this simple example join ',' would suffice, but the real body of
    > the foreach loop is more complicated.


    Unless it is huge, you could just change the print to be push @results, $_;
    and then do the join on @results.


    > What I want to do is something
    > like this:
    >
    > foreach (@ARGV) {
    > print $_;
    > print ',' unless last_element;
    > }
    > print "\n";


    I don't think there is a clean way to do it with a foreach loop. You
    could use a counter, but if you are going to do that I'd just as soon
    change to a C style loop:

    for (my $i=0; $i<=$#ARGV; $i++) {
    print $ARGV[$i];
    print "," unless $i==$#ARGV;
    };

    But actually, I might go for:

    for (my $i=0; $i<@ARGV; $i++) {
    print "," unless $i==0;
    print $ARGV[$i];
    };

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
     
    , Apr 15, 2008
    #3
  4. ShaunJ

    Willem Guest

    ShaunJ wrote:
    ) I want to print a separator between each iteration of a foreach loop,
    ) but not after the last element. How do I avoid printing the last
    ) extraneous comma in the following code snippet?
    )
    ) foreach (@ARGV) {
    ) print $_, ',';
    ) }
    ) print "\n";
    )
    ) In this simple example join ',' would suffice, but the real body of
    ) the foreach loop is more complicated. What I want to do is something
    ) like this:
    )
    ) foreach (@ARGV) {
    ) print $_;
    ) print ',' unless last_element;
    ) }
    ) print "\n";

    One sometimes-seen useful trick is this:

    my $sep = '';
    foreach (@ARGV) {
    print $sep; $sep = ',';
    print $_;
    }


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
     
    Willem, Apr 15, 2008
    #4
  5. ShaunJ

    smallpond Guest

    On Apr 15, 1:24 pm, ShaunJ <> wrote:
    > I want to print a separator between each iteration of a foreach loop,
    > but not after the last element. How do I avoid printing the last
    > extraneous comma in the following code snippet?
    >
    > foreach (@ARGV) {
    > print $_, ',';}
    >
    > print "\n";
    >
    > In this simple example join ',' would suffice, but the real body of
    > the foreach loop is more complicated. What I want to do is something
    > like this:
    >
    > foreach (@ARGV) {
    > print $_;
    > print ',' unless last_element;}
    >
    > print "\n";
    >
    > Thanks,
    > Shaun



    my $notlast = $#ARGV;
    foreach (@ARGV) {
    print $_;
    last unless $notlast;
    $notlast--;
    print ',';
    }
     
    smallpond, Apr 15, 2008
    #5
  6. ShaunJ

    ShaunJ Guest

    On Apr 15, 10:36 am, Frank Seitz <> wrote:
    > ShaunJ wrote:
    > > foreach (@ARGV) {
    > > print $_;
    > > print ',' unless last_element;

    >
    > ^^^^^^^^^^^^
    > \$_ eq \$ARGV[-1]
    >
    > > }
    > > print "\n";


    That works. Thanks, Frank!

    This problem is common enough that it almost warrants special syntax,
    similar to the contine block.

    foreach (@_) {
    print $_;
    } separator {
    print ',';
    }

    Not a serious proposal, just a "wouldn't it be nice if".

    Cheers,
    Shaun
     
    ShaunJ, Apr 15, 2008
    #6
  7. ShaunJ

    Uri Guttman Guest

    >>>>> "W" == Willem <> writes:
    W> One sometimes-seen useful trick is this:

    W> my $sep = '';
    W> foreach (@ARGV) {
    W> print $sep; $sep = ',';

    minor optimization which works but is data dependent:

    print $sep;
    $sep ||= ',';

    W> print $_;

    and $_ is the default for print (as it is for many other funcs ).

    and if it is really just the argv array, join has to be better. the
    array would have to be slightly oversized to make join slow down.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Free Perl Training --- http://perlhunter.com/college.html ---------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Apr 15, 2008
    #7
  8. ShaunJ

    Uri Guttman Guest

    >>>>> "S" == ShaunJ <> writes:

    S> On Apr 15, 10:36 am, Frank Seitz <> wrote:
    >> ShaunJ wrote:
    >> > foreach (@ARGV) {
    >> > print $_;
    >> > print ',' unless last_element;

    >>
    >> ^^^^^^^^^^^^
    >> \$_ eq \$ARGV[-1]
    >>
    >> > }
    >> > print "\n";


    S> That works. Thanks, Frank!

    S> This problem is common enough that it almost warrants special syntax,
    S> similar to the contine block.

    S> foreach (@_) {
    S> print $_;
    S> } separator {
    S> print ',';
    S> }

    S> Not a serious proposal, just a "wouldn't it be nice if".

    perl6 has those flow control blocks. there is FIRST, LAST, BEGIN and a
    bunch of others (all upper case names) that trap conditions/exceptions
    inside their outer blocks.

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Free Perl Training --- http://perlhunter.com/college.html ---------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Apr 15, 2008
    #8
  9. ShaunJ

    Ben Morrow Guest

    Quoth :
    > ShaunJ <> wrote:
    > > I want to print a separator between each iteration of a foreach loop,
    > > but not after the last element. How do I avoid printing the last
    > > extraneous comma in the following code snippet?
    > >
    > > foreach (@ARGV) {
    > > print $_, ',';
    > > }
    > > print "\n";
    > >
    > > In this simple example join ',' would suffice, but the real body of
    > > the foreach loop is more complicated.

    >
    > Unless it is huge, you could just change the print to be push @results, $_;
    > and then do the join on @results.


    print join ',', map {...} @ARGV; is cleaner than pushing onto an
    intermediate array. Or you can set $, and $\ and avoid the join and "\n"
    altogether.

    Ben
     
    Ben Morrow, Apr 15, 2008
    #9
  10. ShaunJ

    Guest

    Ben Morrow <> wrote:
    > Quoth :
    > > ShaunJ <> wrote:
    > > > I want to print a separator between each iteration of a foreach loop,
    > > > but not after the last element. How do I avoid printing the last
    > > > extraneous comma in the following code snippet?
    > > >
    > > > foreach (@ARGV) {
    > > > print $_, ',';
    > > > }
    > > > print "\n";
    > > >
    > > > In this simple example join ',' would suffice, but the real body of
    > > > the foreach loop is more complicated.

    > >
    > > Unless it is huge, you could just change the print to be push @results,
    > > $_; and then do the join on @results.

    >
    > print join ',', map {...} @ARGV; is cleaner than pushing onto an
    > intermediate array.


    Sure, but I thought he was hinting that the contents of the loop were more
    complex than shown, and hence would be more complex than comfortable in a
    map block. Of course, different people do have different comfort levels
    when it comes to cramming complexity into map blocks.

    > Or you can set $, and $\ and avoid the join and "\n"
    > altogether.


    Sure, but then I'd have look up which ones are which (I don't use them
    enough to remember $, from $" from $;, and $\ from $/) and then I'd worry
    about whether I should change them globally (i.e. will code later on use
    them implicitly and get confused, either now or with likely future
    evolution of the script) or if I need to localize them and then go look up
    the details of localizing punctuation variables. Easier to just use join,
    which I don't need to look up. So basically, I don't use them because I
    don't use them enough to feel comfortable using them without looking things
    up, kind of a self-reinforcing situation.

    A Freudian analysis of Perl programming technique.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
     
    , Apr 15, 2008
    #10
  11. ShaunJ

    ff0000 Guest

    Hi everyone,

    > foreach (@ARGV) {
    > print $_;
    > print ',' unless last_element;}
    >
    > print "\n";

    Could this version be useful to you? :

    ---/cut/---
    #!/usr/bin/perl

    my @a = qw(1 2 3 4 5);

    for my $i (0..$#a) {
    print $a[$i] . (($i < $#a) ? ", " : "\n");
    }

    1;
    ---/cut/---

    Bye.
    ff0000
     
    ff0000, Apr 15, 2008
    #11
  12. ShaunJ

    Dave Weaver Guest

    On Tue, 15 Apr 2008 10:48:55 -0700 (PDT), smallpond <> wrote:
    >
    > my $notlast = $#ARGV;
    > foreach (@ARGV) {
    > print $_;
    > last unless $notlast;
    > $notlast--;
    > print ',';
    > }


    Which can be simplified a little to:

    my $notlast = $#ARGV;
    foreach (@ARGV) {
    print $_;
    print ',' if $notlast--;
    }
     
    Dave Weaver, Apr 16, 2008
    #12
  13. On 2008-04-15 19:40, <> wrote:
    > Ben Morrow <> wrote:
    >> Quoth :
    >> > ShaunJ <> wrote:
    >> > > I want to print a separator between each iteration of a foreach loop,
    >> > > but not after the last element. How do I avoid printing the last
    >> > > extraneous comma in the following code snippet?
    >> > >
    >> > > foreach (@ARGV) {
    >> > > print $_, ',';
    >> > > }
    >> > > print "\n";
    >> > >
    >> > > In this simple example join ',' would suffice, but the real body of
    >> > > the foreach loop is more complicated.
    >> >
    >> > Unless it is huge, you could just change the print to be push @results,
    >> > $_; and then do the join on @results.

    >>
    >> print join ',', map {...} @ARGV; is cleaner than pushing onto an
    >> intermediate array.

    >
    > Sure, but I thought he was hinting that the contents of the loop were more
    > complex than shown, and hence would be more complex than comfortable in a
    > map block.


    One could argue that if it is complex it should be put into a sub.
    So you could write

    print join ',', map process_one_arg($_), @ARGV

    where process_one_arg is a suitable descriptive sub name, of course.

    hp
     
    Peter J. Holzer, Apr 17, 2008
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Danny Anderson

    open new file each loop iteration

    Danny Anderson, Jan 21, 2004, in forum: C++
    Replies:
    0
    Views:
    449
    Danny Anderson
    Jan 21, 2004
  2. Rudi
    Replies:
    5
    Views:
    5,307
  3. Nene
    Replies:
    6
    Views:
    363
    John W. Krahn
    Dec 13, 2008
  4. David Karr
    Replies:
    2
    Views:
    225
    Willem
    Apr 7, 2011
  5. Isaac Won
    Replies:
    9
    Views:
    446
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page