代码之家  ›  专栏  ›  技术社区  ›  FMc TLP

如何将Perl哈希转换为更灵活的数据结构?

  •  2
  • FMc TLP  · 技术社区  · 16 年前

    在一个快速而肮脏的Perl脚本中,我有一个如下的数据结构:

    $tax_revenue{YEAR}{STATE}{GOVLEV}{TAX} = integer
    

    哈希键采用如下值:

    YEAR: 1900 .. 2000
    STATE: AK, AL, ... WY
    GOVLEV: state, local
    TAX: type of tax (income, sales, etc.)
    

    此外,哈希键是唯一的。例如,对于 TAX

    # Specify the parameters in any order.
    Tax_rev( qw(1902 WY state property) );
    Tax_rev( qw(state property 1902 WY) );
    
    # Use named parameters.
    Tax_rev(year => 1902, state => 'WY', govlev => 'state', tax => 'property');
    
    # Use wildcards to obtain a list of values.
    # For example, state property tax revenue in 1902 for all states.
    Tax_rev( qw(1902 * state property) );
    

    我最初的倾向是将数据存储为散列,并构建一个或多个实用函数(可能作为类的一部分)来检索值。但后来我想知道是否有更好的策略——除了散列之外,还有其他存储底层数据的方法。任何关于如何解决这个问题的建议都将不胜感激。

    5 回复  |  直到 16 年前
        1
  •  6
  •   Sinan Ünür    16 年前

    请考虑将数据放入 SQLite 数据库然后,您就可以灵活地运行任何需要的查询(通过DBI或SQL的命令行界面)以及获取数据结构,这些数据结构适用于生成给定年份内各州或各州的税收报告,这些州的名称以字母“W”等开头。我假设数据已经采用某种字符分隔格式(制表符、逗号、管道等)因此,可以轻松地将其批量导入SQLite DB,从而节省一些工作和代码。

        2
  •  3
  •   Michael Carman    16 年前

    my @taxdata = (
        { year => 1902, state => 'WY', level => 'state', type => 'property', amount => 500 },
        # ...
    );
    
    my @matches = grep {
        $_->{year}  == 1902    &&
        $_->{level} eq 'state' &&
        $_->{type}  eq 'property'
    } @taxdata;
    

    如果您想对其运行任意查询,这是灵活的,但如果您想能够访问特定记录,则速度较慢。

    DBI 模块来处理连接。

        3
  •  1
  •   pfig    16 年前

    我建议您研究对象系统,例如 Moose

    package MyApp;
    
    use Moose; # use strict automagically in effect
    
    has 'year'   => ( is => 'ro', isa => 'Int', required => 1 );
    has 'state'  => ( is => 'ro', isa => 'Str', required => 1 );
    has 'govlev' => ( is => 'ro', isa => 'Str', required => 1 );
    has 'tax'    => ( is => 'ro', isa => 'Str', required => 1 );
    

    然后在主程序中:

    use MyApp;
    
    my $obj = MyApp->new(
        year   => 2000,
        state  => 'AK',
        govlev => 'local',
        tax    => 'revenue'
    );
    
    # ...
    

        4
  •  1
  •   Peter Kovacs    16 年前

    退房 Data::Diver Tax_rev :

    use Data::Diver qw( Dive );
    
    ...
    $tax_revenue{ 1900 }{ NC }{ STATE }{ SALES } = 1000;
    ...
    
      Dive( \%Hash, qw( 1900 NC STATE SALES ) ) => 1000;
      Dive( \%Hash, qw( 1901 NC STATE SALES ) ) => undef;
    
        5
  •  0
  •   Brad Gilbert    16 年前

    如果您不打算使用对象,我认为数据结构可以正常工作。

    下面是一个例子 Tax_rev()

    my $result = Tax_rev( \%data, qw(state property 1902 WY) );
    

    use strict;
    use warnings;
    use 5.010;