【问题标题】:sum hash of hash values using perl使用 perl 对哈希值进行总和哈希
【发布时间】:2012-11-15 12:58:44
【问题描述】:

我有一个解析 Excel 文件并执行以下操作的 Perl 脚本:它计算 A 列中的每个值、B 列中的元素数,脚本如下所示:

use strict;
use warnings;
use Spreadsheet::XLSX;
use Data::Dumper;
use List::Util qw( sum );

my $col1 = 0;
my %hash;

my $excel = Spreadsheet::XLSX->new('inout_chartdata_ronald.xlsx');


my $sheet = ${ $excel->{Worksheet} }[0];


$sheet->{MaxRow} ||= $sheet->{MinRow};
my $count = 0;
# Iterate through each row
foreach my $row ( $sheet->{MinRow}+1 .. $sheet->{MaxRow} ) {

# The cell in column 1
my $cell = $sheet->{Cells}[$row][$col1];

if ($cell) {

    # The adjacent cell in column 2
    my $adjacentCell = $sheet->{Cells}[$row][ $col1 + 1 ];  
    # Use a hash of hashes

    $hash{ $cell->{Val} }{ $adjacentCell->{Val} }++;

}
}
print "\n", Dumper \%hash;

输出如下所示:

$VAR1 = {
      '13' => {
                'klm' => 1,
                'hij' => 2,
                'lkm' => 4,
              },
      '12' => {
                'abc' => 2,
                'efg' => 2
              }
    };

这很好用,我的问题是:如何访问此输出 $VAR1 的元素以便执行:对于值 13,klm + hij = 3 并获得这样的最终输出:

$VAR1 = {
      '13' => {
                'somename' => 3,
                'lkm' => 4,
              },
      '12' => {
                'abc' => 2,
                'efg' => 2
              }
    };

所以基本上我想要做的是循环遍历我的最终哈希值,并根据唯一键访问其特定元素,最后计算它们的总和。

任何帮助将不胜感激。 谢谢

【问题讨论】:

  • 你想用什么键来计算总和?所有的钥匙?指定的键子集?
  • 是的,这个总和会影响所有的键,13 将有 klm + hij,12 也将有 klm + hij。我举的例子很糟糕,对不起。在更现实的情况下,我会有: $VAR1 = { '13' => { 'somename' => 3, 'lkm' => 4, }, '12' => { 'somename' => 9, 'lkm' => 6 } };

标签: perl excel hash sum


【解决方案1】:

我使用@do_sum 表示您要进行哪些更改。新密钥在脚本中被硬编码。请注意,如果子哈希中不存在密钥($found 标志),则不会创建新密钥。

#!/usr/bin/perl
use warnings;
use strict;

use Data::Dumper;

my %hash = (
            '13' => {
                     'klm' => 1,
                     'hij' => 2,
                     'lkm' => 4,
                    },
            '12' => {
                     'abc' => 2,
                     'efg' => 2
                    }
           );
my @do_sum = qw(klm hij);

for my $num (keys %hash) {
    my $found;
    my $sum = 0;
    for my $key (@do_sum) {
        next unless exists $hash{$num}{$key};
        $sum += $hash{$num}{$key};
        delete $hash{$num}{$key};
        $found = 1;
    }
    $hash{$num}{somename} = $sum if $found;
}

print Dumper \%hash;

【讨论】:

  • 感谢您的帮助,但我想为我的哈希中的所有键执行此操作。我猜需要一个循环吗? (我真的是刚开始学习Perl,谢谢你的理解:))
  • 谢谢,这对您很有帮助。还有一个问题,我想用其他键求和,就像@do_sum,我希望@do_sum2 有例如“abc”和“efg”,我的输出应该看起来像:'somename' => 10, 'othername' => 12. 我需要遍历@do_sum 和@do_sum2,请问我该怎么做?
  • @user1734229:现在应该很容易了。阅读一些文档并尝试找到解决方案。
  • 我知道怎么做。谢谢!! :)
【解决方案2】:

听起来您需要了解Perl References,也许还有Perl Objects,这只是处理引用的好方法。

如您所知,Perl 具有三种基本数据结构:

  • 标量 ($foo)
  • 数组 (@foo)
  • 哈希 (%foo)

问题是这些数据结构只能包含标量数据。也就是说,数组中的每个元素都可以保存一个值,或者哈希中的每个键都可以保存一个值。

在您的情况下,%hash 是一个哈希,其中哈希中的每个条目都引用另一个哈希。例如:

您的%hash 中有一个条目,其键为13。这不包含 标量 值,而是对包含三个键的另一个哈希的引用:klmhijlkm。您可以通过以下语法引用它:

${ hash{13} }{klm} = 1
${ hash{13} }{hij} = 2
${ hash{13} }{lkm} = 4

花括号可能是必需的,也可能不是必需的。但是,%{ hash{13} } 引用了包含在 $hash{13} 中的哈希,所以我现在可以引用该哈希的键。当您谈论数组哈希的哈希值时,您可以想象这会变得更加复杂。幸运的是,Perl 包含一个更简单的语法:

$hash{13}->{klm} = 1
%hash{13}->{hij} = 2
%hash{13}->{lkm} = 4

阅读有关哈希以及如何操作它们的信息。熟悉了这一点后,您就可以开始学习面向对象的 Perl,它以更安全的方式处理引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 2019-03-17
    • 2011-06-08
    相关资源
    最近更新 更多