Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How to get the number of fields found by split without a warning?

by Rudif (Hermit)
on Dec 08, 2003 at 20:36 UTC ( #313223=perlquestion: print w/replies, xml ) Need Help??

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

Replies are listed 'Best First'.
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.

      Dittos to talexb, but I like scalar:

      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"
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

    You can get this without a dummy array assignment with:

    my $n = scalar @{[split ',', $str]};

    The 'scalar' is optional, but I like it for readability.

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;

      Doesn't work. split is optimized into splitting into no more fields than one more than you request. See perldoc -f split:
      When assigning to a list, if LIMIT is omitted, Perl supplies a LIMIT one larger than the number of variables in the list, to avoid unnecessary work.

      Using ()= you request 0 fields, so in scalar context, you get 1.

      print my $n = () = split /-/, 'a-b-c';
      1
      
        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.

      my $n =()= split ',', $str;

      er... that seems to give me 1, whatever the length of the string

      Am I missing something?

      dave

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
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
    Many thanks to all who responed.

    I will keep my second solution

    $n = @{[ split ',', $str ]}; print "$n\n";
    which was seconded above by Zed_Lopez.

    Rudif

      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.

        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
        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.


        Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://313223]
Approved by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2023-11-28 12:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?