【问题标题】:Counting number of occurrences of a string inside another (Perl)计算另一个字符串中出现的次数(Perl)
【发布时间】:2016-06-21 17:40:27
【问题描述】:

计算某个字符串出现在较大字符串中的次数的最快方法是什么?我最好的猜测是将该字符串的所有实例都替换为空,计算长度差并除以子字符串的长度,但这似乎相当慢,我需要分析大量数据。

【问题讨论】:

  • 可能想看看这个......虽然它是从 1999 年开始的,而且很可能还有其他方法可以有效地做这种事情:perlmonks.org/…

标签: regex perl substring


【解决方案1】:

您可以捕获字符串,然后计算它们。可以通过使用() 将列表上下文应用于捕获来完成:

my $x = "foo";
my $y = "foo foo foo bar";
my $c = () = $y =~ /$x/g;  # $c is now 3

您还可以捕获到数组并对数组进行计数。原理相同,手法不同:

my @c = $y =~ /$x/g;
my $count = @c;

【讨论】:

  • @ronash 这是相同的解决方案。一个使用临时变量,另一个不使用。您也可以使用my $count = @c = $y =~ /$x/g,但您可以简单地忽略@c 并使用()。如果您不关心实际匹配,那么哪个是最好的。
  • 如果$x 包含某些正则表达式字符,这不起作用,因为$x 被解释为正则表达式。添加\Q 来解决这个问题,例如。 /\Q$x/g。请参阅quotemeta 了解更多信息。
  • 关于性能的问题:my $c = () = $y =~ /$x/g 和(恕我直言)更漂亮的my $c = scalar($y =~ /$x/g) 有什么区别?我猜它们是一样的,但如果后者效率不高,我会使用前者。 (我的理解是 scalar() 呼叫不是必需的,正如下面 Brian Roach 的回答中所指出的那样。)
  • @AdamKatz 区别在于第一个解决方案有效,第二个无效。
【解决方案2】:
my $string = "aaaabbabbba";
my @count = ($string =~ /a/g);
print @count . "\n";

my $count = ($string =~ s/a/a/g);

【讨论】:

  • 呃,是的......这是一个正则表达式,你可以匹配任何东西。
  • 在您的第二个解决方案中, tr/a/a/g 不是更好的解决方案,因为您自己替换字符并且 tr 比 s 更快?
【解决方案3】:

您可以使用全局正则表达式。比如:

my @matches = $bigstring =~ /($littlestring)/g;
my $count = @matches;

【讨论】:

  • 这似乎是最简单的解决方案,所以我想我会使用它,除非有更快的解决方案?谢谢!
  • 我不确定正则表达式的速度,但我确信只使用匹配操作比替换更快。而且我想不出与正则表达式无关的解决方案(否则会很有趣!)
【解决方案4】:

为了完整起见,您可以在循环中重复调用 index 函数并计算它返回字符串中子字符串索引的所有次数,并更改起始位置。这将避免使用正则表达式,并且在我的测试中比正则表达式解决方案要快一些。

我已经从这里改编了一个子来做到这一点:http://www.misc-perl-info.com/perl-index.html

sub occurrences {

    my( $x, $y ) = @_;

    my $pos = 0;
    my $matches = 0;

    while (1) {
        $pos = index($y, $x, $pos);
        last if($pos < 0);
        $matches++;
        $pos++;
    }   

    return $matches;
}

【讨论】:

    猜你喜欢
    • 2011-07-01
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多