I want to report the number of times a character occurs in a string. Thanks to Is there a better way to count occurrence of char in a string?, the first part of the following works elegantly.
#!/usr/bin/env perl
use strict; use warnings;
my $string='dog
#
####
pig horse';
# https://stackoverflow.com/questions/34437248/is-there-a-better-way-to-count-occurrence-of-char-in-a-string
print join('','# occurs ',my$dummy=()=$string=~/[#]/g,' times in',"\n",$string,"\n",);
# the following yields no count at all:
print join('','# occurs ',()=$string=~/[#]/g,' times in',"\n",$string,"\n",);
Is there a way to eliminate the seemingly gratuitous declaration of the $dummy variable? I'd like to use that integer directly in join
without first declaring a variable to grab the value.
CodePudding user response:
That trick
$dummy = () = $string =~ /[#]/g
works because the whole assignment-expression
() = EXPR
itself is in a scalar context, being assigned to a scalar ($dummy), so it returns the length of the would-be list which EXPR returns (it being in list context).
So impose the scalar context on it
say join('', '# occurs ', scalar( () = $string =~ /#/g ),' times');
I've shortened the string for easier reading, and employed say instead of print ... "\n". †
See this page for more on () = EXPR and its context, and the links in it.
Not sure that this is really much prettier but it does what is asked.
But if you really always want just one character's count than tr does it much more nicely
print join('', '# occurs ', $string =~ tr/#//,' times in',"\n",$string,"\n",);
† If one were to really just print then there is no need to form a string with join '' since print takes a list and effectively concatenates elements without anything in between, so joins them
say '# occurs ', scalar( () = $string =~ /#/g ), " times in\n", $string;
or, for a single character
say '# occurs ', $string =~ tr/#//, ' times in', "\n", $string;
(But I take it that the print is just an example for this question and that you really need a string...)
