用于匹配数组中字符串的Perl计数

时间:2015-07-10 11:16:33

标签: arrays string perl

我有一个充满字符串的数组。我想在此数组中检查一个特定字符串是否多次,然后打印错误警告。

我在List :: MoreUtils中使用了true方法来计算我的匹配。 在我的数组中,我有一些字符串,其子字符串与同一数组中的其他字符串相同 因此,如果我在数组中检查相同的字符串是否多于一次,我会收到错误警告,即使可能只有另一个字符串具有相同的子字符串。 我尝试通过将字符串长度添加为模式来解决问题(因此字符串和长度必须相等,以便弹出错误消息),但这也不起作用。
我的代码看起来像这样:

use strict;
use warnings;
use List::MoreUtils 'true';

my @list = ("one", "two", "three", "onefour", "one");

foreach my $f (@list) {  

        my $length = length($f);
        my $count = true { $length && "$f"} @list;

           if($count > 1) {
                    print "Error with: ", $f, " counted ", $count, " times!\n";
                }
       $count = 0;
    }

使用此代码,我根本不会收到错误警告,即使“one”在数组中是两次。如果我不将长度作为true方法的模式包含,那么字符串“one”将被计数三次。

2 个答案:

答案 0 :(得分:4)

我不会使用true - 看起来你正在尝试做的就是选择'重复,并不关心子串。

my %seen;
$seen{$_}++ for @list; 
print grep { $seen{$_} > 1 } @list; 

所以要复制你的测试:

my %count_of;
$count_of{$_}++ for @list;  
foreach my $duplicate (  grep { $count_of{$_} > 1 } @list ) {
    print "Error: $duplicate was seen $count_of{$duplicate} time\n";
}

答案 1 :(得分:1)

你实际上并不匹配任何东西。我在你的代码中添加了调试输出。

f: one
length: 3
true { 3 && one} one: one
true { 3 && one} two: one
true { 3 && one} three: one
true { 3 && one} onefour: one
true { 3 && one} one: one
count: 5
Error with: one counted 5 times!
f: two
length: 3
true { 3 && two} one: two
true { 3 && two} two: two
true { 3 && two} three: two
true { 3 && two} onefour: two
true { 3 && two} one: two
count: 5
Error with: two counted 5 times!
f: three
length: 5
true { 5 && three} one: three
true { 5 && three} two: three
true { 5 && three} three: three
true { 5 && three} onefour: three
true { 5 && three} one: three
count: 5
Error with: three counted 5 times!
f: onefour
length: 7
true { 7 && onefour} one: onefour
true { 7 && onefour} two: onefour
true { 7 && onefour} three: onefour
true { 7 && onefour} onefour: onefour
true { 7 && onefour} one: onefour
count: 5
Error with: onefour counted 5 times!
f: one
length: 3
true { 3 && one} one: one
true { 3 && one} two: one
true { 3 && one} three: one
true { 3 && one} onefour: one
true { 3 && one} one: one
count: 5
Error with: one counted 5 times!

让我们来看看:

$f

因此,您始终拥有字符串true的长度,该长度大于0,因此在Perl中的结果为$f。然后你有true。这也是'',因为所有不是空字符串(@list)的字符串都是真的。

使用true函数迭代@list中的所有元素。该块总是如此。因此,您始终可以获得my %count; $count{$_}++ for @list; my @unique = keys %count; # unsorted # see Sobrique's answer with grep for sorted the same way as before 中元素数量的计数。

如果您只想删除双重出现,可以使用哈希来计算它们。

uniq

然后List::MoreUtils中还有my @unique = uniq @list;

grep

如果你想知道每个元素是否是任何其他元素的子字符串,你可以使用Perl's builtin index,它在另一个字符串中查找字符串的位置,以及foreach my $f (@list) { if ( my @matches = grep { $_ ne $f && index( $_, $f ) > -1 } @list ) { warn "$f is a substr of: @matches"; # will auto-join on $, } } __END__ one is a substr of: onefour at /code/scratch.pl line 91. one is a substr of: onefour at /code/scratch.pl line 91.

ne

现在当然这并没有得到0和4都是"一个"因为index。请注意,-1如果根本没有匹配则返回my @list = ( "one", "two", "three", "onefour", "one" ); my %count; $count{$_}++ for @list; warn sprintf 'Number of duplicates: %d', @list - keys %count if @list != keys %count; my $count_substr; foreach my $f (@list) { $count_substr++ if grep { $_ ne $f && index( $_, $f ) > -1 } @list; } warn sprintf 'Number of substring duplicates: %d', $count_substr if $count_substr;

your comment on Sobrique's answer之后

修改

要仅在有重复项(或副字符重复项)时收到警告,只需计算它们即可。在任何地方都没有发生任何修改:

{{1}}