Rudif has asked for the wisdom of the Perl Monks concerning the following question:
Fellow monks,
I wanted get the number of fields found by split into a scalar, and I got it, but with a warning thrown in
#!/usr/bin/perl -w
use strict;
my $str = "a,b,c,d,e";
my $n = split ',', $str;
print "$n\n";
Use of implicit split to @_ is deprecated at H:\dev\perl\perlmonks\spl
+it-it.pl line 4.
5
perlfunc says this
In scalar context, returns the number of fields found and splits into the @_ array.
Use of split in scalar context is deprecated, however, because it clobbers your subroutine arguments.
OK, that's helpful.
But what is the best way to get rid of this warning?
I came up with these two so far
my @n = split ',', $str;
$n = @n;
print "$n\n";
$n = @{[ split ',', $str ]};
print "$n\n";
Any other ideas?
Rudif
Re: How to get the number of fields found by split without a warning?
by talexb (Chancellor) on Dec 08, 2003 at 20:55 UTC
|
As you've probably read, split returns an array, so I'd recommend you take advantage of that and afterwards count the number of elements in the array.
my $str = "a,b,c,d,e";
my @n = split ',', $str;
print "There were " . ($#n+1) . " elements.\n";
The '+1' is required because array offsets start at zero.
--t. alex
Life is short: get busy!
Update: Or, as Corion pointed out, scalar(@n) which is much clearer.
| [reply] [d/l] [select] |
|
use strict;
my $str = "a,b,c,d,e";
my @n = split /,/, $str;
print scalar @n, "\n"
Hanlon's Razor - "Never attribute to malice that which can be adequately explained by stupidity"
| [reply] [d/l] |
Re: How to get the number of fields found by split without a warning?
by Zed_Lopez (Chaplain) on Dec 08, 2003 at 21:26 UTC
|
my $n = scalar @{[split ',', $str]};
The 'scalar' is optional, but I like it for readability.
| [reply] [d/l] |
Re: How to get the number of fields found by split without a warning?
by duff (Parson) on Dec 08, 2003 at 21:08 UTC
|
If you're really determined to do this, you could use the =()= pseudo-operator:
my $n =()= split ',', $str;
Update: Quite right bart, I left out the 3rd arg to split(), the correct code is as follows.
my $n =()= split ',', $str, -1;
| [reply] [d/l] [select] |
|
print my $n = () = split /-/, 'a-b-c';
→
1
| [reply] [d/l] |
|
Still not a problem (but you knew that)(:
E:\>perl -le"die $_ = () = split ',','a,b,c,d,e,f,g',-1"
7 at -e line 1.
MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!" | I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README). | ** The third rule of perl club is a statement of fact: pod is sexy. |
| [reply] [d/l] |
|
|
| [reply] [d/l] |
Re: How to get the number of fields found by split without a warning?
by Roy Johnson (Monsignor) on Dec 08, 2003 at 21:32 UTC
|
If you don't want to actually split but just want to know how many fields split would return, try one of the methods illustrated here:
#!perl
use strict;
use warnings;
my $str = "a,b,c,d,e";
my $n = 1 + $str =~ tr/,//; # Field separator is a single char
print "$n\n";
$n = 1 + (() = $str =~ /,/g); # Field separator is a regex
print "$n\n";
The PerlMonk tr/// Advocate
| [reply] [d/l] |
Re: How to get the number of fields found by split without a warning?
by Rudif (Hermit) on Dec 08, 2003 at 23:48 UTC
|
$n = @{[ split ',', $str ]};
print "$n\n";
which was seconded above by Zed_Lopez.
Rudif
| [reply] [d/l] |
|
Why make another copy of the array with @{[ ... ]}? I would rather do this instead -
$n = scalar( split ',', $str );
print "$n\n";
Ok, lets give it a test -
use strict;
use Benchmark qw/timethese cmpthese/;
my $str = join ',',map{('a'..'z')[rand 26] x (1 + rand 5)}0..1000;
cmpthese( timethese(10000, {
'split_anonymous' => '&split_anonymous',
'split_simple' => '&split_simple',
}) );
sub split_anonymous
{
my $n = @{[split ',', $str]};
#print "$n\n";
}
sub split_simple
{
my $n = scalar split ',', $str;
#print "$n\n";
}
And the comparison -
Benchmark: timing 10000 iterations of split_anonymous, split_simple...
split_anonymous: 19 wallclock secs (19.05 CPU) @ 525.02/s (n=10000)
split_simple: 16 wallclock secs (15.77 CPU) @ 634.32/s (n=10000)
Rate split_anonymous split_simple
split_anonymous 525/s -- -17%
split_simple 634/s 21% --
The benchmark result show that a simple split without making an anonymous copy is 20% faster.
| [reply] [d/l] [select] |
|
As davido points out, my question is : how to get rid of the warning. And in as few keystrokes as possible, without a significant time overhead.
Finally, I decided to try the obvious solution : turn off warnings locally.
sub split_simple_quiet
{
no warnings;
my $n = scalar split ',', $str;
#print "$n\n";
}
This does the job and costs almost nothing in time, as the expanded benchmark shows:
Use of implicit split to @_ is deprecated at H:\dev\perl\perlmonks\ben
+ch.pl line 23.
Benchmark: timing 10000 iterations of split_anonymous, split_simple, s
+plit_simple_quiet...
split_anonymous: 24 wallclock secs (15.55 usr + 0.00 sys = 15.55 CPU)
+ @ 643.00/s (n=10000)
split_simple: 20 wallclock secs (12.23 usr + 0.00 sys = 12.23 CPU) @
+817.80/s (n=10000)
split_simple_quiet: 18 wallclock secs (12.15 usr + 0.01 sys = 12.16 C
+PU) @ 822.57/s (n=10000)
Rate split_anonymous split_simple split_si
+mple_quiet
split_anonymous 643/s -- -21%
+ -22%
split_simple 818/s 27% --
+ -1%
split_simple_quiet 823/s 28% 1%
+ --
Rudif | [reply] [d/l] [select] |
|
I like Roger's my $qty = scalar ( split ',', $string ); method, however, it takes us back to where we started, by generating a warning message about implicit splitting into @_ being deprecated (if the code is tested under -w or use warnings;).
Unfortunately, the solution is either to turn off warnings for that section of code, or to revert back to the other solution which makes an extra copy: my $qty = @{[ split ',', $string ]};.
Of course, if all you're trying to do it count commas except for trailing ones, you could probably just loop through the string instead.
| [reply] [d/l] [select] |
|
|