2011-04-29 123 views
2

我知道似乎很混乱。我试图“画出”这个数据结构:如何更新散列数组中的值,该散列值位于perl中散列的散列中?

hash-> key - >((key) - > [(key,value),(key,value),(key,value)... ], (key,value))

所以有第一个关键字,它的值被括在圆括号中。散列的第一个键的值是两个键,一个(右边的)是另一个简单的键,值对。另一个(左边的)键值是散列数组。我能够使用以下行的代码来更新“右”键,值对:

$hash{$parts[1]}{"PAGES"} += $parts[2]; 

其中$份[1]和$份[2]是从数组只是元素。我+ =从我的哈希值的“右”键值对。我现在需要做的是更新“左”键,值对 - 散列哈希中的散列数组。这是我如何初始化这两个键,值对数组中的哈希散列:

$hash{$printer}{"PAGES"} = 0; 
$hash{$printer}{"USERS"} = [@tmp]; 

这是我多次尝试哈希值的数组中访问和更新的值之一:

$hash{$parts[1]}{"USERS"}[$parts[0]] += $parts[2]; 

我只是无法弄清楚这个正确的语法。如果有人可以帮助我,我会很感激。谢谢。

编辑:我猜一个更尖锐的问题是:我如何从哈希数组中获得哈希键(记住数组是散列哈希)?

编辑:将此添加到代码:

#Go through each user to check to see which user did a print job and add the page 
#count to their total 
#$parts[0] is the user name, $parts[1] is the printer name, $parts[2] is the page 
#count for the current print job 
for(my $i=0;$i<$arr_size;$i++) 
{ 
    my $inner = $hash{$parts[1]}{"USERS"}[$i]; 
    my @hash_arr = keys %$inner; 
    my $key = $hash_arr[0]; 

    #problem line - need to compare the actual key with $parts[0] 
    #(not the key's value which is a number) 
    if($hash{$parts[1]}{"USERS"}[$i]{$key} eq $parts[0]) 
    { 
     $hash{$parts[1]}{"USERS"}[$i]{$parts[0]} += $parts[2]; 
    } 
} 

编辑:哎呦嘿嘿,这是我需要的。它仍然不是那里,但这是我正在寻找的种类:

if($key eq $parts[0]) 
{ 
    $hash{$parts[1]}{"USERS"}[$i]{$parts[0]} += $parts[2]; 
} 

回答

1

编辑以回应编辑的问题:如何从散列数组中获取散列键(请记住该数组位于散列散列中)。

use strict; 
use warnings; 

my %h; 
$h{printer}{PAGES} = 0; 
$h{printer}{USERS} = [ 
    {a => 1, b => 2}, 
    {c => 3, d => 4}, 
    {e => 5, f => 6}, 
]; 

# Access a particular element. 
$h{printer}{USERS}[0]{a} += 100; 

# Access one of the inner hashes. 
my $inner = $h{printer}{USERS}[1]; 
$inner->{$_} += 1000 for keys %$inner; 

# Ditto, but without the convenience variable. 
$h{printer}{USERS}[2]{$_} += 9000 for keys %{ $h{printer}{USERS}[2] }; 

use Data::Dumper qw(Dumper); 
print Dumper \%h; 

输出:

$VAR1 = { 
    'printer' => { 
      'PAGES' => 0, 
      'USERS' => [ 
        { 
        'a' => 101, 
        'b' => 2 
        }, 
        { 
        'c' => 1003, 
        'd' => 1004 
        }, 
        { 
        'e' => 9005, 
        'f' => 9006 
        } 
        ] 
      } 
    }; 
+0

是的,我使用Data :: Dumper来查看值,并且我得到所有0的地方应该有1或4等。 – 2011-04-29 13:20:49

+0

这几乎就是我想要做的,只是使用散列而不是数字(即使用其中一个散列元素的键作为数组索引来获取其相应的值并对其进行操作)。 – 2011-04-29 14:16:40

+0

@john史密斯不知道我跟着你,但看到编辑的回应。 – FMc 2011-04-29 17:13:08

0

我无法理解您的描述结构。

我的建议是避免像坏邻居那样的结构恶化的结构。

人们最终做出这种维修噩梦的一个原因是他们使用XML::Simple

无论您的示例中出现什么原因,请自己帮忙,并防止可怕的数据结构被创建。总是有替代品。如果你描述这个问题,人们将能够提出一些建议。

+0

我想出了很多思考和讨论之后这个数据结构。我需要跟踪由17台打印机中每台打印机打印的页面数以及这些打印机上打印的用户数量。我从解析系统日志中获取此信息以了解打印事件。打印事件日志中的每一行都包含用户,打印机和打印页数。因此,我创建这与打印的页面,并且其值是“用户名,打印页数”键和值的对的阵列的“用户”键每个打印机相关联。 – 2011-04-29 13:19:32

+0

我尊重在这样的数据结构的到达的努力。去过也做过。 (很久以前)。智慧仍然是为了避免这样的结构,因为你为什么要在这里发布。这很难保持,而且很脆弱。会有变化,然后你会再次努力去理解你的数据结构。 - 使用对象([Moose](http://search.cpan.org/dist/Moose/)),使用XML和XPath,或使用SQL。后两个听起来像是过度杀伤,所以我会选择#1,这应该是最简单的。 – Lumi 2011-04-29 13:27:42

0

你所描述的结构的方式是有点动摇不了我,但是嵌入其他结构中访问数组引用正是如此做,用简单的例子结构:

my $ref = {k => [1, 3, 5, 6, 9]}; 

下面,6的值被递增到7:

$ref->{k}->[3] += 1; 

有关->运算符的更多详细信息,请参见perlref,但简而言之,箭头左侧的表达式可以是任何返回引用的表达式。在某些情况下,运营商->是可选的,但它是最好的留在了清晰度。

0

我还没有解码的结构。但是,我要发表两点意见:

  1. 使用->语法糖。例如,$hash->{key}->[2]->{key}比尝试解析没有语法糖的事情要清楚一点:${{hash}{key}}[1]{key}(如果这甚至是正确的...)

  2. 使用面向对象Perl查看此结构。这听起来并不像可怕。在Perl中,对象是可以为你处理肮脏工作的子例程。看看perldoc perlboot。这是我用来理解面向对象的Perl如何工作的。你甚至不需要创建一个完整的独立模块。对象定义可以存在于同一个Perl脚本中。面向Perl的

使用对象保持混乱的主程序以外,并使其更容易维护程序。另外,如果您必须修改结构,则无需搜索整个代码即可找到要更改的所有位置。通过语法糖,您可以更轻松地查看结构的位置。

比较这monstrosity这个object oriented monstrosity。两个程序都做同样的事情。我很早以前就写了第一篇文章,并且发现很难保证我以面向对象的风格从头开始重写它。 (如果有人想知道,他们是Subversion的预先提交钩子)。

+0

感谢您的建议,但我所做的工作。也许它是comp。 SCI。我从高中毕业的学生,​​但我想尝试创建一个适合我的场景的独特数据结构。我认为这是我的老板在产出方面所追求的。谢谢大家。 – 2011-04-29 20:48:33

+0

@john smith - “独特”数据结构没有错。我建议的语法糖只是简单地理解一下哪里会发生什么。这是散列数组的哈希,还是这是一个包含数组哈希的散列?语法糖只有帮助。 OO Perl是处理这些复杂结构的最好方法。你在一个地方隔离他们的访问。而且,良好的面向对象编程技术使得它明显体现了你的结构代表。我在Perl中编写OO的90%是为了一次性的事情。我永远不会再使用它。但是,我的程序更容易维护。 – 2011-05-02 17:54:19