0

I want to count the values of an array inside a hash and add them to the hash. My code looks like this:

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

                    $timestamp = $1 if $line=~ /^\s*<timestamp>(.*)</;
                    $timestamp =~ s/^(\d\d\d\d-\d\d-\d\d)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>(.*)</;
            }

Output

   '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.'
                                  ],
                   }

What I would like to have is something like this:

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

Can anyone help me with this? Thanks in advance.

5
  • hi melpomene , yes correct. I will edit it Commented Apr 5, 2019 at 7:46
  • Tip: ALWAYS use use strict; use warnings; Commented Apr 5, 2019 at 16:21
  • Tip: Use an XML parser like XML::LibXML! It's not any more complicated, and it will save you so many headaches! Commented Apr 5, 2019 at 16:21
  • Tip: my ($date) = $timestamp =~ /^([^T])/; and my ($date) = split(/T/, $timestamp); are much cleaner ways of extracting the date. Commented Apr 5, 2019 at 16:21
  • Tip: You are using $errorCode even when you don't set it!!! Use my ($error_code) = $line =~ /<errorCode>(.*)</ ? $1 : ""; Commented Apr 5, 2019 at 16:23

1 Answer 1

3

You can just do

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

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

There's no need to check for the existence of intermediate structures and create them manually. Autovivification will take care of that.

Just add another layer of hash key access and increment the value. You'll end up with a count of values.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.