Good way to un-chomp an array

S

Suresh Govindachar

Hello,

What is a good way (with respect to speed)
to un-chomp an array?

for(my $i=0; $i<scalar @lines; $i++)
{
$lines[$i] .= "\n";
}

Thanks,

--Suresh
 
G

Gunnar Hjalmarsson

Suresh said:
What is a good way (with respect to speed)
to un-chomp an array?

for(my $i=0; $i<scalar @lines; $i++)
{
$lines[$i] .= "\n";
}

This is simpler code:

print map "$_\n", @lines;

As regards speed, I have no idea. If that is a concern of yours, do a
benchmark ("perldoc Benchmark").
 
S

Scott W Gifford

Suresh Govindachar said:
Hello,

What is a good way (with respect to speed)
to un-chomp an array?

This was the fastest way I could come up with:

$_ .= "\n"
foreach @lines;

I benchmarked it, your original, and a map-based solution, and found
it was about 30% faster than your original, and about twice as fast as
map:

Benchmark: timing 50 iterations of for_index, foreach, map...
for_index: 18 wallclock secs (17.44 usr + 0.31 sys = 17.75 CPU) @ 2.82/s (n=50)
foreach: 13 wallclock secs (12.54 usr + 0.17 sys = 12.71 CPU) @ 3.93/s (n=50)
map: 37 wallclock secs (35.93 usr + 0.55 sys = 36.48 CPU) @ 1.37/s (n=50)

#!/usr/bin/perl

use Benchmark;

our @arr = (1..100_000);

sub test1
{
my @a = @arr;
$_ .= "\n"
foreach @a;
}

sub test2
{
my @a = @arr;
for(my $i=0; $i<scalar @a; $i++)
{
$a[$i] .= "\n";
}
}

sub test3
{
my @a = @arr;
@a = map { $_."\n" } @a;
}

timethese(50, {
foreach => \&test1,
for_index => \&test2,
map => \&test3,
});

-----ScottG.
 
S

Suresh Govindachar

Gunnar Hjalmarsson said:
Suresh said:
What is a good way (with respect to speed)
to un-chomp an array?

for(my $i=0; $i<scalar @lines; $i++)
{
$lines[$i] .= "\n";
}

This is simpler code:

print map "$_\n", @lines;

Doesn't the above code print? I actually want to
change the array @lines.
As regards speed, I have no idea. If that is a concern of yours, do a
benchmark ("perldoc Benchmark").

OK about doing benchmarks; would like to have candidate
codes to do the benchmark on.

--Suresh
 
G

Gunnar Hjalmarsson

Suresh said:
Gunnar said:
Suresh said:
What is a good way (with respect to speed)
to un-chomp an array?

for(my $i=0; $i<scalar @lines; $i++)
{
$lines[$i] .= "\n";
}

This is simpler code:

print map "$_\n", @lines;

Doesn't the above code print? I actually want to
change the array @lines.

Then do:

$_ .= "\n" for @lines;

Besides, according to Scott's benchmark, that's fastest as well.

However, I can't help to ask: Was it motivated to chomp the lines in
the first place? Did you for instance do something like this:

my @lines = <FILE>;
for (@lines) {
chomp;
...

??
In that case, maybe it would have been possible to keep the trailing
newline characters all through instead?

And another question: Was it motivated to load all the lines into
memory, or would it have been sufficient to process them one at a time:

while (<FILE>) {
...
 
M

Matt Garrish

Suresh Govindachar said:
Hello,

What is a good way (with respect to speed)
to un-chomp an array?

for(my $i=0; $i<scalar @lines; $i++)

So many ugly C-style for loops lately:

for my $i (0..$#lines)
{
$lines[$i] .= "\n";
}

You could question why you're adding newlines (i.e., can it wait until you
output the array, and do the alternatives at that stage -- map or join, for
example -- make a difference), but otherwise there's no complexity in the
loop you've posted to improve on.

Matt
 
M

Matt Garrish

Scott W Gifford said:
This was the fastest way I could come up with:

$_ .= "\n"
foreach @lines;

I benchmarked it, your original, and a map-based solution, and found
it was about 30% faster than your original, and about twice as fast as
map:

Benchmark: timing 50 iterations of for_index, foreach, map...
for_index: 18 wallclock secs (17.44 usr + 0.31 sys = 17.75 CPU) @ 2.82/s (n=50)
foreach: 13 wallclock secs (12.54 usr + 0.17 sys = 12.71 CPU) @ 3.93/s (n=50)
map: 37 wallclock secs (35.93 usr + 0.55 sys = 36.48 CPU) @ 1.37/s (n=50)


for_index: 11 wallclock secs (11.44 usr + 0.02 sys = 11.45 CPU) @ 4.37/s
(n=50)
foreach: 10 wallclock secs (10.06 usr + 0.02 sys = 10.08 CPU) @ 4.96/s
(n=50)

Not sure why you're getting such a large discrepancy.

Matt
 
T

Tad McClellan

Scott W Gifford said:
This was the fastest way I could come up with:

$_ .= "\n"
foreach @lines;


If we want unchomp(), then we'd better:

$_ .= $/ foreach @lines;

so it will work even when the input record separator is not the default.
 
5

510046470588-0001

Scott W Gifford said:
This was the fastest way I could come up with:

$_ .= "\n"
foreach @lines;

I benchmarked it, your original, and a map-based solution, and found
it was about 30% faster than your original, and about twice as fast as
map:

it may make a difference whether
the original array of strings is still needed or not.
(that's not clear from the context)
destructive operations are usually more efficient,
but if the original needs to be preserved,
it requires deep copying first,
which also should enter the benchmark.

Klaus Schilling
 
M

Matt Garrish

John Bokma said:
Still ugly :-(

Everyone else's baby is always uglier... : )

Granted there are other ways that don't require the array index, but it was
only meant as a drop-in replacement for the original.

Matt
 
J

Jürgen Exner

Matt said:
Everyone else's baby is always uglier... : )

Granted there are other ways that don't require the array index, but
it was only meant as a drop-in replacement for the original.

You almost never need the array index in Perl. I would guess over 98% of all
array processing is done one element at a time and for that the canonical
form is

for (@array) {
process_element;
}

The only exception (i.e. the only case where you need an array index) is if
in order to process a given element you need dynamic access to other array
element, e.g. in bubble sort to compare the element with its neighbor. But
in real life those case are surprisingly rare.

jue
 
A

Abhinav

Jürgen Exner said:
You almost never need the array index in Perl. I would guess over 98% of all
array processing is done one element at a time and for that the canonical
form is

for (@array) {
process_element;
}

Disgressing from the topic, could anyone please explain how (if at all)
this is different from

foreach (@array) {
process_element;
}

And when to use this instead of the former ?
The only exception (i.e. the only case where you need an array index) is if
in order to process a given element you need dynamic access to other array
element, e.g. in bubble sort to compare the element with its neighbor. But
in real life those case are surprisingly rare.

TIA
 
S

Sam Holden

Disgressing from the topic, could anyone please explain how (if at all)
this is different from

foreach (@array) {
process_element;
}

And when to use this instead of the former ?

It is exactly the same.

Use that when you want to type an extra four characters.

Use:

foreach($i=0;$i<10;++$i) {
print "$i\n";
}

When you want to confuse yourself later.
 
T

Tad McClellan

Abhinav said:
Jürgen Exner wrote:

Disgressing from the topic, could anyone please explain how (if at all)


The docs for foreach might explain foreach better than some
random person on Usenet...

See the "Foreach Loops" section in perlsyn.pod

The C<foreach> keyword is actually a synonym for the C<for> keyword, so
this is different from

foreach (@array) {
process_element;
}


They are not different.

And when to use this instead of the former ?


Whenever you are not playing Perl Golf. :)
 
J

Jürgen Exner

Abhinav said:
Disgressing from the topic, could anyone please explain how (if at
all) this is different from

foreach (@array) {
process_element;
}

It is four keystrokes shorter
And when to use this instead of the former ?

When you want to save 4 keystrokes.
For further details please see "perldoc perlsyn"

jue
 
R

Randal L. Schwartz

Eugene> these are the same. 'for' and 'foreach' are synonyms

Although a "for" loop is distinct from a "foreach" loop.

Sometimes, you spell it f-o-r, and pronounce it "foreach".

print "Just another Perl hacker,"; # the original
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,159
Messages
2,570,880
Members
47,417
Latest member
DarrenGaun

Latest Threads

Top