通过哈希计算 - PERL

时间:2017-11-21 15:00:52

标签: perl hash count

我有一个人们从中订购物品的地方数据库。我解析了列表以获得城市和州,所以它打印像这样 - 城市,州(纽约,纽约)等....

我使用变量$ city和$ state但是我想计算每个城市和州发生的次数所以看起来像这样 - 城市,州,伯爵(西雅图,华盛顿州8)

除了计数之外,我所有的工作都在运行..我正在使用哈希,但我无法弄清楚这个哈希有什么问题:

if ($varc==3) {
        $line =~ /(?:\>)(\w+.*)(?:\<)/;
        $city = $1;
    }
    if ($vars==5) {
        $line =~ /(?:\>)((\w+.*))(?:\<)/;
        $state = $1;

        # foreach $count (keys %counts){
        #   $counts = {$city, $state} {$count}++;
        #   print $counts;
        # }

    print "$city, $state\n";

    }
foreach $count (keys %counts){
$counts = {$city, $state} {$count}++;
print $counts;
}

2 个答案:

答案 0 :(得分:1)

您可以建立一个&#34;位置&#34;而不是打印城市和州。两个项目的字符串,并使用以下计数代码:

# Declare this variable before starting to parse the locations.
my %counts = ();

# Inside of the loop that parses the city and state, let's assume
# that you've got $city and $state already...

  my $location = "$city, $state";
  $counts{$location} += 1;
}

# When you've processed all locations then the counts will be correct.
foreach $location (keys %counts) {
  print "OK: $location => $counts{$location}\n";
}

# OK: New York, NY => 5
# OK: Albuquerque, NM => 1
# OK: Los Angeles, CA => 2

答案 1 :(得分:1)

这将是答案和代码审查的混合。我会从警告开始。

您正尝试使用正则表达式解析看起来像XML的内容。虽然this can be doneit should probably not be done。改为使用现有的解析器。

我怎么知道?尖括号之间的东西看起来像格式是XML,除非你有一个非常奇怪的CSV文件。

#             V            V
$line =~ /(?:\>)(\w+.*)(?:\<)/;

另请注意,您无需转义<>,它们在正则表达式中没有特殊含义。

现在你的代码。

首先,请确保始终use strictuse warnings,以便您了解出错的内容。我可以告诉你不是因为你的循环中的$count没有my

什么是$vars(带有s),什么是$varc(带有c)。我猜这与 s tate和 c 有关。是列号吗?在XML文件中?咦。

$line =~ /(?:\>)((\w+.*))(?:\<)/;

为什么有两个捕获组,都捕获相同的东西?

无论如何,您想要计算州和城市的每个组合发生的频率。

foreach $count (keys %counts){
$counts = {$city, $state} {$count}++;
print $counts;
}

您运行此代码吗?即使没有strict,它也会出现语法错误。我甚至不确定它应该做什么,所以我不能告诉你如何解决它。

要实现计数,您需要一个哈希值。你得到了那个部分。但是你需要在文件读取循环之外声明该哈希变量。然后,您需要在哈希中为您的城市和州组合创建一个键,并在每次看到该组合时递增它。

my %counts;    # declare outside the loop
while ( my $line = <$fh> ) {
    chomp $line;
    if ( $varc == 3 ) {
        $line =~ /(?:\>)(\w+.*)(?:\<)/;
        $city = $1;
    }
    if ( $vars == 5 ) {
        $line =~ /(?:\>)((\w+.*))(?:\<)/;
        $state = $1;

        print "$city, $state\n";

        $count{"$city, $state"}++;    # increment when seen
    }
}

您必须先解析整个文件,然后才能知道每个组合在文件中的频率。因此,如果要将这些打印在一起,则必须在读取文件的循环之外移动打印,并在稍后通过键迭代%count散列。

my %counts;    # declare outside the loop
while ( my $line = <$fh> ) {
    chomp $line;
    if ( $varc == 3 ) {
        $line =~ /(?:\>)(\w+.*)(?:\<)/;
        $city = $1;
    }
    if ( $vars == 5 ) {
        $line =~ /(?:\>)((\w+.*))(?:\<)/;
        $state = $1;

        $count{"$city, $state"}++;    # increment when seen
    }
}

# iterate again to print final counts
foreach my $item ( sort keys %counts ) {
    print "$item $counts{$item}\n";
}