Print a separator between each iteration of a foreach loop

Print a separator between each iteration of a foreach loop

am 15.04.2008 19:24:59 von Shaun Jackman

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

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 19:36:26 von Frank Seitz

ShaunJ wrote:

> foreach (@ARGV) {
> print $_;
> print ',' unless last_element;
^^^^^^^^^^^^
\$_ eq \$ARGV[-1]
> }
> print "\n";

Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 19:40:13 von jurgenex

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

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 19:44:17 von xhoster

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.

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 19:47:24 von Willem

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

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 19:48:55 von smallpond

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 ',';
}

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 20:00:16 von Shaun Jackman

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

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 20:11:04 von Uri Guttman

>>>>> "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 ------ uri@stemsystems.com -------- 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 ---------

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 20:13:16 von Uri Guttman

>>>>> "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 ------ uri@stemsystems.com -------- 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 ---------

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 20:31:59 von Ben Morrow

Quoth xhoster@gmail.com:
> 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

Re: Print a separator between each iteration of a foreach loop

am 15.04.2008 21:40:09 von xhoster

Ben Morrow wrote:
> Quoth xhoster@gmail.com:
> > 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.

Re: Print a separator between each iteration of a foreach loop

am 16.04.2008 00:15:24 von ff0000

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

Re: Print a separator between each iteration of a foreach loop

am 16.04.2008 12:55:04 von Dave Weaver

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

Re: Print a separator between each iteration of a foreach loop

am 17.04.2008 14:16:32 von hjp-usenet2

On 2008-04-15 19:40, xhoster@gmail.com wrote:
> Ben Morrow wrote:
>> Quoth xhoster@gmail.com:
>> > 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