Perl6:对BagHash / Matching感到困惑

时间:2016-08-13 02:28:30

标签: regex perl6 multiset

我正在尝试使用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;

我错过了什么?

2 个答案:

答案 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;