我正在尝试使用a1
计算正则表达式的匹配,并得到奇怪的结果。
c.c2
输出是:
BagHash
我正在使用的测试用例是:
my $fh = open "versions.txt";
my $versions = BagHash.new();
while (defined my $line = $fh.get) {
my $last = '';
if $line ~~ /(\d+)\.?(\d*)/ {
say 'match ' ~ $/[0];
if $last !eq $/[0] {
say 'not-same: ' ~ $/[0];
$versions{$/[0]}++
}
$last = $/[0];
}
else {
$last = '';
}
}
say 'count: ' ~ $versions.elems;
我错过了什么?
答案 0 :(得分:4)
每次迭代都会重置$ last。另外,不要相信说。它旨在用于避免使用无限列表泛滥终端或日志文件。使用dd
(Rakudo内部)或模块转储调试输出。如果您使用dd
,我们会看到$/[0]
包含Match
,这是一个不适合生成哈希密钥的复杂结构。
# my @lines = slurp('version.txt');
my @lines = ('version=234.234', 'version=999');
my BagHash $versions.=new;
for @lines {
ENTER my $last = '';
if .Str ~~ /(\d+) '.'? (\d*)/ {
$versions{$0.Str}++ if $last ne $0.Str;
$last = $0.Str
}else{
$last = ''
}
};
dd $versions;
# OUTPUT«BagHash $versions = ("234"=>1,"999"=>1).BagHash»
BagHash的重点在于它的构造函数会为你做计算。如果你一直提供懒惰列表,这可能相当有效。
my @lines = ('version=234.234', 'version=999');
dd BagHash.new(@lines».split('=')».[1]);
# OUTPUT«("234.234"=>1,"999"=>1).BagHash»
答案 1 :(得分:4)
错误#1您几乎肯定希望在循环之外进行$last
声明,因此您不会将其重置为''
错误#2你可能只想更新$last
的状态,你发现的版本号不是所有行
Bug#3您使用Match对象作为HashBag的键而不是版本的字符串值。您可以将匹配强制为与~$/[0]
匹配的字符串,但只有$0
也是此快捷方式。
我清理了你的代码并得到了下面的代码,但实际上远非惯用的Perl 6:
my $fh = open "versions.txt";
my $versions = BagHash.new();
my $last = '';
for $fh.lines -> $line {
if $line ~~ /(\d+)\.?(\d*)/ {
say 'match ' ~ $/[0];
if $last ne $/[0] {
say 'not-same: ' ~ $/[0];
$versions{~$/[0]}++;
$last = $/[0];
}
}
else {
$last = '';
}
}
say $versions;
say 'count: ' ~ $versions.elems;
如果是扔掉代码,我个人会写如下:
my $versions = "versions.txt".IO.lines.comb(/(\d+)\.?(\d*)/).Bag;
say $versions.elems;
如果您以后想要该文件或对每一行执行更多操作,或者这是用于生产:
my %versions;
for "versions.txt".IO.lines -> $line {
if $line ~~ /((\d+)\.?(\d*))/ {
%versions{$0}++;
}
}
say %versions.elems;