开发者

How do I multiply each member of array by a scalar in perl?

Here is the code...

use strict;
use warnings;

my @array= (1,2,3,4,5);
my $scalar= 5;

@array= $scalar*@array;

print @array;

Need something that can perform similar function wi开发者_StackOverflow社区th little code. Thanks!


Use foreach.

foreach my $x (@array) { $x = $x * $scalar; }


You can try this:

@array = map { $_ * $scalar } @array;

or more simply:

map { $_ *= $scalar } @array;


Howabout this:

foreach(@array)
{ $_ *= $scalar }

As you see, you can modify the array in-place as it's traversed.


I don't know the scope of your need. IFF you are doing numerical data manipulation, the Perl Data Language (PDL) takes an array of numerical data, creates a "piddle" object from it and overloads mathematical operations to "vectorize" their operation. This is a very efficient system for doing numerical processing. Anyway here is an example:

#!/usr/bin/perl

use strict;
use warnings;

use PDL;

my $pdl_array = pdl([1,1,2,3,5,8]);
print 2*$pdl_array;

__END__
gives:
[2 2 4 6 10 16]


This comment is for SoloBold.

Here is a test of the map approach:

#!/usr/bin/perl                                                                                                                                                                                                          

use strict;
use warnings;
use Benchmark;

my @array = ();
push(@array, (1) x 1000000);
my $scalar = 5;

my $startTime = new Benchmark();

@array = map { $_ * $scalar } @array;

my $stopTime = new Benchmark();

print STDOUT "runtime: ".timestr(timediff($stopTime, $startTime), 'all')." sec\n";

Here is a test of the foreach approach:

#!/usr/bin/perl                                                                                                                                                                                                          

use strict;
use warnings;
use Benchmark;

my @array = ();
push(@array, (1) x 1000000);
my $scalar = 5;

my $startTime = new Benchmark();

foreach my $x (@array) { $x = $x * $scalar; }

my $stopTime = new Benchmark();

print STDOUT "runtime: ".timestr(timediff($stopTime, $startTime), 'all')." sec\n";

Here is the system I'm running on:

bash-3.2$ perl --version
This is perl, v5.8.8 built for darwin-2level
...
bash-3.2$ uname -a
Darwin Sounder.local 10.7.0 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386

Here were results from one test:

bash-3.2$ ./test.map.pl
runtime:  4 wallclock secs ( 0.41 usr  0.70 sys +  0.00 cusr  0.00 csys =  1.11 CPU) sec
bash-3.2$ ./test.foreach.pl
runtime:  0 wallclock secs ( 0.13 usr  0.00 sys +  0.00 cusr  0.00 csys =  0.13 CPU) sec

These times are fairly reproducible on the same machine, and the results are somewhat repeatable on a dual-core Linux box:

[areynolds@fiddlehead ~]$ perl --version
This is perl, v5.8.8 built for x86_64-linux-thread-multi
...
[areynolds@fiddlehead ~]$ uname -a
Linux fiddlehead.example.com 2.6.18-194.17.1.el5 #1 SMP Mon Sep 20 07:12:06 EDT 2010 x86_64 GNU/Linux
[areynolds@fiddlehead ~]$ ./test.map.pl
runtime:  0 wallclock secs ( 0.28 usr  0.05 sys +  0.00 cusr  0.00 csys =  0.33 CPU) sec
[areynolds@fiddlehead ~]$ ./test.foreach.pl
runtime:  0 wallclock secs ( 0.09 usr  0.00 sys +  0.00 cusr  0.00 csys =  0.09 CPU) sec

The ratio of performance on the OS X box is 8.53x slower for map versus foreach. On the Linux box, 3.67x slower for the same.

My Linux box is dual-core and has a slightly faster cores than my single-core OS X laptop.

EDIT

I updated Perl from v5.8.8 to v5.12.3 on my OS X box and got a considerable speed boost, but map still performed worse than foreach:

sounder:~ alexreynolds$ perl --version
This is perl 5, version 12, subversion 3 (v5.12.3) built for darwin-multi-2level
...
sounder:~ alexreynolds$ ./test.map.pl
runtime:  0 wallclock secs ( 0.45 usr  0.08 sys +  0.00 cusr  0.00 csys =  0.53 CPU) sec
sounder:~ alexreynolds$ ./test.foreach.pl
runtime:  1 wallclock secs ( 0.18 usr  0.00 sys +  0.00 cusr  0.00 csys =  0.18 CPU) sec

This goes from 8.53x worse to 2.94x worse. A fairly substantial improvement.

The Linux box performed slightly worse with upgrading its Perl installation to v5.12.2:

[areynolds@basquiat bin]$ perl --version    
This is perl 5, version 12, subversion 2 (v5.12.2) built for x86_64-linux-thread-multi
...
[areynolds@basquiat bin]$ /home/areynolds/test.map.pl
runtime:  1 wallclock secs ( 0.29 usr  0.07 sys +  0.00 cusr  0.00 csys =  0.36 CPU) sec
[areynolds@basquiat bin]$ /home/areynolds/test.foreach.pl
runtime:  0 wallclock secs ( 0.08 usr  0.00 sys +  0.00 cusr  0.00 csys =  0.08 CPU) sec

This goes from 3.67x worse to 4.5x worse — not so good! It might not always pay to upgrade, just for the heck of it.


it seem unfortunate to me that Larry didn't allow

$scalar operator (list)

or

(list) operator $scalar

Sure map or loops can do it, but the syntax is so much cleaner like above.

Also (list) operator (list)

makes sense too if the 2 are equal length.

Surprised Larry didn't allow these, just saying.. I guess in this case there were (n-1) ways to do it.

Like

my @a = 'n' . (1..5); my @a = 2 * (1..5);

or even my @a = 2 * @b;

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜