【问题标题】:Updating a value in a Hash of an array or hashes更新一个或多个数组的哈希值
【发布时间】:2020-10-26 23:29:53
【问题描述】:

我正在像这样初始化一个哈希表:-

my %AllCountStats = ();
foreach my $Log (@LogList) {
    foreach my $Func (keys %AllFuncNames) {
        push @{$AllCountStats{$Log}}, {Func=>$Func,Count=>0};
    }
}
print Dumper (\%AllCountStats);

Dumper 输出如下所示:-

$VAR1 = {
    'log.1' => [
        {
            'Count' => 0,
            'Func' => 'Function A'
        },
        {
            'Func' => 'Function B',
            'Count' => 0
        },
    }
    'log.2' => [
        {
            'Count' => 0,
            'Func' => 'Function A'
        },
        {
            'Count' => 0,
            'Func' => 'Function X'
        },
    };

现在我需要遍历散列数组的散列,并通过手术更新每个 Func 的 Count 值。使用上面的示例,我应该发出什么命令来将 log.1 的 Func=Function A 值更新为新的值(即不是 0)?这是我尝试在何处/如何进行更新的示例...

foreach $Log (@LogList) {
    foreach (sort {$a->{SCmdLineNum} <=> $b->{SCmdLineNum}} @{$SweepStats{$Log}}) {
        $SCmd = $_->{SCmd};
        my $inner = $AllCountStats{$Log}{$SCmd}{Count};
        $inner->{$_}++ for keys %$inner;
    }
}

但它不起作用。当 $inner 有效地变为 $AllCountStats{log.1}{Function B}{Count} 时,我怎样才能干净地更新它的 Count 值?

【问题讨论】:

  • %SweepStats 来自哪里?请尝试编辑代码,以便我们运行它并重现您的问题。 “不工作”是什么意思?
  • 嗨,@choroba,您实际上不需要关心 %SweepStats——主要问题是如何通过手术更新 %AllCountStats 中的 Count 字段。当我尝试发出 $inner->{$_}++ 时,它报告上一行是非法的哈希引用,所以我认为它的格式不正确。
  • Re "你真的不需要关心 %SweepStats",好吧,没错,但我们确实需要知道你想知道哪个 Count @{$SweepStats{$Log}} 的给定元素的增量。
  • 提示:sort 没用。循环中的任何内容都不关心访问元素的顺序。

标签: perl hashmap


【解决方案1】:

$AllCountStats{$Log} 是对数组的引用,但您将其视为对哈希的引用。

这个

$AllCountStats{$Log}{$SCmd}{Count}

应该是

$AllCountStats{$Log}[$i]{Count}

目前尚不清楚您希望 $i 获得什么值。我们会回到那个。


接下来,以下是没有意义的:

my $inner = $AllCountStats{$Log}[$i]{Count};
$inner->{$_}++ for keys %$inner;

$inner 只是一个数字,而不是哈希引用。你想要的

my $inner = $AllCountStats{$Log}[$i]
++$inner->{Count};

或者只是

++$AllCountStats{$Log}[$i]{Count};

返回$i。我最好的猜测是你想增加记录的Count,它的Function值等于$SCmd

for my $log_name (@LogList) {
   my $log = $AllCountStats{$log_name};

   for my $stats_rec (@{$SweepStats{$Log}}) {  # Useless sort removed.
      my $SCmd = $stats_rec->{SCmd};
      for my $log_rec (@$log) {
         ++$log_rec->{Count} if $log_rec->{Function} eq $SCmd;
      }
   }
}

如果是这样的话,如果你构建 %AllCountStats 这样看起来会更简单

my %AllCountStats = (
   'log.1' => {
       'Function A' => 0,
       'Function B' => 0,
   },
   ...
);

那么,你只需要

for my $log_name (@LogList) {
   my $log = $AllCountStats{$log_name};
   for my $stats_rec (@{$SweepStats{$Log}}) {
      ++$log->{ $stats_rec->{SCmd} };
   }
}

【讨论】:

  • 感谢您的建议!你的假设是正确的,你的建议是有效的。很抱歉没有更清晰的原始帖子,但提取问题的本质是痛苦的(许多复杂的日志、专有细节、数千个函数等,但只需要修改 Count)。
【解决方案2】:

请看下面这段代码(应该很容易理解)

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my $log   = 'log.1';
my $func  = 'Function A';
my $count = 5;

my %AllCountStats = (
    'log.1' => [
        {
            'Count' => 0,
            'Func' => 'Function A'
        },
        {
            'Func' => 'Function B',
            'Count' => 0
        }
    ],
    'log.2' => [
        {
            'Count' => 0,
            'Func' => 'Function A'
        },
        {
            'Count' => 0,
            'Func' => 'Function X'
        }
    ]
);

for ( @{$AllCountStats{$log}} ) {
    $_->{'Count'} = $count if $_->{'Func'} eq $func;
}

say Dumper(\%AllCountStats);

【讨论】:

  • @'Polar Bear' 非常感谢——这正是我需要做的,而且效果很好!
【解决方案3】:

结构的第二层似乎是一个数组,而不是散列。你需要方括号。

%AllCountStats 中,您将数字存储在“计数”键下。此数字存储在$inner 中,然后您尝试将其取消引用为哈希。

改为直接增加值:

++$AllCountStats{$Log}[$SCmd]{Count}

【讨论】:

  • (我怀疑$SCmd 是一个数字。我认为它不止于此)
  • 正确的$SCmd其实是一个复杂的文本字符串——需要使用index() != -1来验证匹配等
  • 那我不明白你要如何使用复杂的文本字符串来索引数组。
猜你喜欢
  • 2019-05-01
  • 2022-01-12
  • 2020-12-13
  • 2016-08-08
  • 2017-04-24
  • 1970-01-01
  • 1970-01-01
  • 2014-04-18
  • 1970-01-01
相关资源
最近更新 更多