如何在Perl中存储这些数据?

时间:2016-04-17 19:20:37

标签: perl data-structures

基本上,我制作了一堆Perl代码,目前产生如下输出:

if: 12
for: 26
rof: 26
fi: 27
for: 25
rof: 25
fi: 27
...some more backtracking...
if: 9
fi: 9
for: 26
rof: 26

每一行都是由正则表达式中的代码生成的事件,格式为:title: position

(我没有询问正则表达式;它完美地描述了我编写的一个简单的CFG。不要提及它的任何内容,我只需要帮助存储然后检索它的数据。已打印。)

我希望sub mark将此数据放入数据结构中。但我不确定最好的方法。我需要能够以三种方式检索数据(以每个方式为例):

  • 标题:标题为for的哪些事件?
  • 职位:在12号位发生了什么事件?
  • 订单:最后一件事是什么?

我也想避免重复的提案。如果fi: 27作为第四和第八个事件发生,我想要一个条目,其顺序是4,8,之类的数组。

请记住,我对Perl非常缺乏经验,我很欣赏代码示例(解释如何使用迭代进行存储和检索)。我知道似乎有三种类型的数据结构:$@%。我没有比这更进一步,因为Perl的结构与Java(我最有经验)完全不同。

随时请我澄清任何事情。

我的代码很简单,除了正则表达式:

sub mark{
    my ($title, $position)= @_;
    print "\n";
    print $title;
    print $position;
}

$re = qr{
((?&line))

|(*F)(?:
   (?'line'  (?&if)|(?&for))
   (?'if'    if \((?&exp)*\)\{\s*(?{mark("if: ", pos)})(?&line)*(?{mark("fi: ", pos)})\s*\})
   (?'for'   for\((?&exp)*\)\{\s*(?{mark("for: ",pos)})(?&line)*(?{mark("rof: ",pos)})\s*\})
   (?'eq'    [=])
   (?'exp'   (?&abc)(\s?(?&eq)\s?(?&num)+)?)
   (?'num'   [0-9])
   (?'abc'[a-z])
   (?'space' \s)
)}xm;

# I've been changing the following 'string' to test different stuff
# This is the run that produced the sample data
# 'oops;' doesn't follow the grammar rules, so it shows how the regex may backtrack

'if(true){
  for(i = 5){
  }
  oops;
}' =~ /$re/
     and print "\n\n$1\n\n";

2 个答案:

答案 0 :(得分:2)

我创建了一个数组来保持顺序(@ordered),下面的代码存储了标题和位置。其他两个哈希值,%by_title和%by_position,只是使查找更快。它们只将索引存储到@ordered数组。

use feature qw{ say };
use constant {
    TITLE    => 0,
    POSITION => 1,
};

my (%by_title, %by_position, @ordered);
my $order = 0;
sub mark{
    my ($title, $position)= @_;
    push @{ $by_title{$title} }, $order;
    push @{ $by_position{$position} }, $order;
    push @ordered, [ $title, $position ];
    ++$order;
}

# ...

say "Last: @{ $ordered[-1] }";
say 'Other at the same position:',
    join ', ', map "@{ $ordered[$_] }",
               @{ $by_position{ $ordered[-1][POSITION] } };
say 'Other with the same title: ',
    join ', ', map "@{ $ordered[$_] }",
               @{ $by_title{ $ordered[-1][TITLE] } };

答案 1 :(得分:0)

您需要的是存储标题的哈希值,以及存储位置的数组引用。这看起来像下面这样:

$VAR1 = {
          'rof: ' => [
                       '26',
                       '25',
                       '24',
                       '23',
                       '26'
                     ],
          'for: ' => [
                       '26',
                       '25',
                       '24',
                       '23',
                       '26'
                     ],
          'fi: ' => [
                      '27',
                      '27',
                      '27',
                      '27',
                      '12',
                      '11',
                      '10',
                      '9'
                    ],
          'if: ' => [
                      '12',
                      '11',
                      '10',
                      '9'
                    ]
        };

我通过做出这些改变来制作它。

use strict;
use warnings;
use Data::Dumper;

my %foo;
sub mark{
    my ($title, $position)= @_;

    push @{ $foo{$title} }, $position;
}

# your regex and match here

print Dumper \%foo;

要访问这些内容,您可以使用keys keyword进行迭代,并使用@{ $foo{$key} }取消引用以访问数组。

您应该阅读perldataperlrefperlreftut,您可能也对re pragma's debug mode感兴趣。