Reputation: 85
How to count the number of zeros in a string of this type:
my $string = '11100000000010000011000';
Upvotes: 1
Views: 260
Reputation: 1968
Edit: TLDR: The following are two most common and efficient solutions (mentioned also by other answers). For appreciation of how they work read the rest of the answer.
my $count = $string =~ tr/0//; # solution 1
my $count = () = $string =~ /0/g; # solution 2
The long story
So my first naive solution was this:
my $string = '11100000000010000011000';
my @ar = split //,$string;
@b = grep { $_ == 0 } @ar;
print scalar @b,"\n";
While it works, it is not really a "perl-style" solution. So I looked around and found this article: https://www.effectiveperlprogramming.com/2010/12/count-the-number-of-things-in-a-string/ which shows how to count the number of zeroes and ones at the same time.
Based on that I created the following:
my $string = '11100000000010000011000';
my $count = () = $string =~ /0/g;
print "count: ",$count,"\n";
The most intriguing are probably the empty parentheses. They are explained in this interesting article about perl idioms: https://www.perlmonks.org/?node_id=527973
Perl expression results may depend on their "context", so by using something as a scalar or as an array I tell perl what I expect to get. ()
"forces array context". Without it I would expect a scalar, which would get me true
/false
result of that match.
Once we have an array we force scalar context
by assigning the array to a scalar variable and it then returns its length.
Edit: Other solutions suggested using tr///
in the same fashion. It seems that it is maybe even more popular and it may be faster in some situations (it has to modify the string though). But the principle of the "list context" stays the same. https://perldoc.perl.org/perlop#Regexp-Quote-Like-Operators search for "list context" on that page if you want to learn more about it. It applies to most operators. But their behavior may differ.
Upvotes: 4
Reputation: 851
Whenever it comes to counting items in Perl, I have learned, seen and used Hashes, something like this would help:
use strict;
use warnings;
# your string
my $string = '11100000000010000011000';
# has to store the item counts
my %count;
# split: read the string character by character
for my $z (split //, $string) {
# add to the count
$count{$z}++;
}
# read the keys of hash count
# and sort the output
for my $k (sort {$a <=> $b} keys %count) {
# display the counts
print "$k has $count{$k} occurrences\n";
}
Results:
[user@localhost ~]$ perl zero.pl
0 has 17 occurrences
1 has 6 occurrences
Upvotes: 2
Reputation: 241808
The traditional and fast way is to use tr
:
my $count = $string =~ tr/0//;
Upvotes: 7