как подсчитать повторяющиеся значения массива с помощью hashreference

#perl #hash

#perl #хэш

Вопрос:

Я хочу подсчитать значения массива внутри хэша и добавить их в хэш. Мой код выглядит следующим образом:

 while(my $line=<$fh>) {

                    $timestamp = $1 if $line=~ /^s*<timestamp>(.*)</;
                    $timestamp =~ s/^(dddd-dd-dd)T.*s*$/$1/;
                    $errorCode= $1 if $line=~ /^s*<errorCode>(.*)</;

                    $hash{$timestamp}             = {} unless($hash{$timestamp});
                    $hash{$timestamp}{$errorCode} = [] unless($hash{$timestamp}{$errorCode});

                                    push @{$hash{$timestamp}{$errorCode}}, $1 if $line =~ /<errorText>(.*)</;
            }
  

Вывод

    '2019-04-05' => {    '5005' => [
                                    'Dies ist kein aktives Konto',
                                    'Dies ist kein aktives Konto'
                                  ],
                        '7112' => [
                                    'Eingabefelder nicht richtig gefuellt.',
                                    'Eingabefelder nicht richtig gefuellt.',
                                    'Eingabefelder nicht richtig gefuellt.'
                                  ],
                   }
  

Я хотел бы иметь что-то вроде этого:

 '2019-04-05' => {    '5005' => { 'Dies ist kein aktives Konto' => 2 },
                     '7112' => { 'Eingabefelder nicht richtig gefuellt.' => 3 },
                }
  

Кто-нибудь может мне помочь с этим? Заранее спасибо.

Комментарии:

1. привет, Мельпомена, да, правильно. Я отредактирую его

2. Совет: ВСЕГДА используйте use strict; use warnings;

3. Совет: используйте анализатор XML, такой как XML::LibXML! Это не сложнее, и это избавит вас от стольких головных болей!

4. Совет: my ($date) = $timestamp =~ /^([^T])/; и my ($date) = split(/T/, $timestamp); гораздо более чистые способы извлечения даты.

5. Совет: вы используете $errorCode , даже если вы не установили его!!! Использовать my ($error_code) = $line =~ /<errorCode>(.*)</ ? $1 : "";

Ответ №1:

Вы можете просто сделать

 while (my $line=<$fh>) {
    $timestamp = $1 if $line=~ /^s*<timestamp>(.*)</;
    $timestamp =~ s/^(dddd-dd-dd)T.*$/$1/;
    $errorCode= $1 if $line=~ /^s*<errorCode>(.*)</;

    $hash{$timestamp}{$errorCode}{$1}   if $line =~ /<errorText>(.*)</;
}
  

Нет необходимости проверять наличие промежуточных структур и создавать их вручную. Об этом позаботится автозаполнение.

Просто добавьте еще один уровень доступа к хэш-ключу и увеличьте значение. В итоге вы получите количество значений.