Hello,
I have a file like below that contains datewise value for every hour for 2 locations. I need to add the value for the same hours for ServerA and ServerB. Using Hashes, I am able to add the server value per hour. But cannot pass it to a table. I am selecting "Loc" via a dropdown to use a switch to select the data.
Input File:

Loc    Date     TYPE    Server  Hour  Val
EMEA    1-Sep   TYPE-A  Server-A    00  4
EMEA    1-Sep   TYPE-A  Server-B    00  4
EMEA    1-Sep   TYPE-A  Server-A    01  5
EMEA    1-Sep   TYPE-A  Server-B    01  5
EMEA    1-Sep   TYPE-A  Server-A    02  15
EMEA    1-Sep   TYPE-A  Server-B    02  15
EMEA    2-Sep   TYPE-A  Server-A    00  4
EMEA    2-Sep   TYPE-A  Server-B    00  4
EMEA    2-Sep   TYPE-A  Server-A    01  5
EMEA    2-Sep   TYPE-A  Server-B    01  5
EMEA    2-Sep   TYPE-A  Server-A    02  15
EMEA    2-Sep   TYPE-A  Server-B    02  15

OUTPUT in HTML Table

Hours/Date    00    01    02    03    04    05    06    07    08    09    10    11    12    13    14    15    16    17    18    19    20   21    22    23
Sep-1    08    10    30
Sep-2    08    10    30

This is what I have done sofar...but out is not coming in correct way

print $q->start_multipart_form(
                       -name    => 'main_form');
        print "<tr><td></td></tr>";
        print "<tr><td></td></tr>"; 
        print "<td>";
        print '<span style=font-family:Arial;>Select the feature to Display &nbsp&nbsp</span>&nbsp&nbsp&nbsp', $q->textfield(-name=>'textcontent',
                        -default=>'Type a value...',
                        -size=>50,
                        -maxlength=>80,
                        -align=>'LEFT');  
        print "</td></tr>";
        print "<tr><td>"; 
        print submit(-name=>'Send',
                    -value=>'Submit',
                    -align=>'CENTER');

        my $filename = param('textcontent');
        print "<br><br><br>";
        print "The Location you have selected is: $filename";
        print "<br><br><br>";

        my $k; my $i=0;my $file;my @argv;my %res;my $key;my $date, my $token, my $server, my $hour, my $peak;my $flag = 0;my $tablecontent;my @th;
        open(DATA, "../cgi-bin/file.txt") || die("Could not open file!");
        while(<DATA>) {  
            ($key, $date, $token, $server, $hour, $peak)= split;
            if ($key eq $filename){
                switch($filename){
                    case "EMEA" {$res{$date}{$hour}->{PEAK}+=$peak;$flag=1}
                    case "APAC" {$res{$date}{$hour}->{PEAK}+=$peak;$flag=1}
                    else { print "previous case not true" }
                }
            }
        }
        if ($flag){
        pgm_fil();
        }

        sub pgm_fil{
            my $q = new CGI;
            $q->header;
            $q->start_html();
            my $tablecontent=[$q->th(['Date/Hours','00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'])];
            foreach my $key (sort {$a<=>$b} keys %res){
                foreach my $user (keys %{$res{$key}}){
                    foreach my $user1 (keys %{$res{$key}{$user}}){
                        push @$tablecontent,$q->td([$key,$res{$key}{$user}{$user1}]);
                    }
                }
            }
            print $q->table( { border => 1, -width => '50%', -align=>'left'},
                      $q->Tr( $tablecontent),
                 );
        }
    print end_form; 

Hi vivek.vivek,

Going by your output show, rightly like you are doing, one can use an hash. But since what is really needed is the hour and the number of value one can skip the rest.

What i don't get in your post is what you pointed out as the problems. But cannot pass it to a table. How do you mean by this?

I can also see that you are using CGI, that is fast becoming old fashion. See Perl different frameworks like Dancer and the likes.

Something like this below, show how you could achieve your aim.

use warnings;
use strict;

<DATA>; # remove file header
my %data;

while (<DATA>) {
    my ( $date, $hr, $value ) =
      ( split /\s+/ => $_ )[ 1, 4, 5 ];
    if ( !exists $data{$date}{$hr} ) {
        $data{$date}{$hr} = $value;
    }
    else {
        $data{$date}{$hr} += $value;
    }
}

print sprintf "%s\t%2s\n", "Date/Hours", join( "   " => 0 .. 23 ), $/;

for my $key ( sort keys %data ) {
    print $key, "\t\t", map { $_, "  " } values %{ $data{$key} };
    print $/;
}

__DATA__
Loc    Date     TYPE    Server  Hour  Val
EMEA    1-Sep   TYPE-A  Server-A    00  4
EMEA    1-Sep   TYPE-A  Server-B    00  4
EMEA    1-Sep   TYPE-A  Server-A    01  5
EMEA    1-Sep   TYPE-A  Server-B    01  5
EMEA    1-Sep   TYPE-A  Server-A    02  15
EMEA    1-Sep   TYPE-A  Server-B    02  15
EMEA    2-Sep   TYPE-A  Server-A    00  4
EMEA    2-Sep   TYPE-A  Server-B    00  4
EMEA    2-Sep   TYPE-A  Server-A    01  5
EMEA    2-Sep   TYPE-A  Server-B    01  5
EMEA    2-Sep   TYPE-A  Server-A    02  15
EMEA    2-Sep   TYPE-A  Server-B    02  15

Thank You very much. I am checking it and doing some tweaking to fit the complete code I have. Will post in case I need any more help.

Thanks

Edited 1 Year Ago by vivek.vivek

One small problem here...I am not getting in the correct order within the hash value.

$VAR1 = '2-Sep';
$VAR2 = {
          '01' => 10,
          '00' => 8,
          '02' => 30
        };
$VAR3 = '1-Sep';
$VAR4 = {
          '01' => 10,
          '00' => 8,
          '02' => 30
        };

If I add 03 it will come in some other order.

I wish the output be like

$VAR1 = '2-Sep';
$VAR2 = {
          '00' => 8,
          '01' => 10,
          '02' => 30
        };
$VAR3 = '1-Sep';
$VAR4 = {
          '00' => 8,
          '01' => 10,
          '02' => 30
        };

Hi,

If I add 03 it will come in some other order.

How do you mean by adding 03?
Please don't forget that when you are using Data::Dumper, you must past a reference NOT to have the presentation like you are having it presently.

Something like this:

print Dumper \%hash_data;

Moreso, don't forget that values in hash are do not follow a particular order, you might have to sort the the key.

Hope that works, if not you might want show what data you have.

Hi,

I am using the same input file. But added another lines " EMEA 1-Sep TYPE-A Server-A 03 25 & EMEA 1-Sep TYPE-A Server-B 03 15" as below.

EMEA    1-Sep   TYPE-A  Server-A    00  4
EMEA    1-Sep   TYPE-A  Server-B    00  4
EMEA    1-Sep   TYPE-A  Server-A    01  5
EMEA    1-Sep   TYPE-A  Server-B    01  5
EMEA    1-Sep   TYPE-A  Server-A    02  15
EMEA    1-Sep   TYPE-A  Server-B    02  15
EMEA    1-Sep   TYPE-A  Server-A    03  25
EMEA    1-Sep   TYPE-A  Server-B    03  15
EMEA    2-Sep   TYPE-A  Server-A    00  4
EMEA    2-Sep   TYPE-A  Server-B    00  4
EMEA    2-Sep   TYPE-A  Server-A    01  5
EMEA    2-Sep   TYPE-A  Server-B    01  5
EMEA    2-Sep   TYPE-A  Server-A    02  15
EMEA    2-Sep   TYPE-A  Server-B    02  15

Also using "print Dumper(%data);"

Output of the code is as below:

>perl file_test.pl
$VAR1 = '2-Sep';
$VAR2 = {
          '01' => 10,
          '00' => 8,
          '02' => 30
        };
$VAR3 = '1-Sep';
$VAR4 = {
          '01' => 10,
          '03' => 40,
          '00' => 8,
          '02' => 30
        };
Date/Hours      0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
1-Sep          10 40 8 30
2-Sep          10 8 30

But the real output should be

 Date/Hours     0 1 2 3
 1-Sep          8 10 30 40
 2-Sep          8 10 30

I hope I am clear now.

yeah, you are clear..
Check this piece of code:

print $key, "\t\t", map { $_, " " } values %{ $data{$key} };

in line 21 in my previous post to this:

print $key, "\t\t", map { $data{$key}{$_}, " " } sort keys %{ $data{$key} };

that should do. I hope you understand what is going on there?

Yep, I got it...Thanks!
I need to know more thing, if i need to get the max from the rage of hash values what should I change? I tried using List::Util module.

Eg:

Sep 1 40
Sep 2 30

Edited 1 Year Ago by vivek.vivek

I think I got a solution...working on it.

my $max = $data{each %{$data{$key} }};
                $data{$key}{$_} > $max and $max = $data{$key}{$_} for keys %{ $data{$key} };

Oh I have to add one more column in the data - Hr.

I have changed the code to get Max value from each 5 min in a hour.

I need

Date/Hours     0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
1-Sep          30 50 70 40
2-Sep          8 10 30

Sofar the code is:

#!/usr/bin/perl 
use strict;
use warnings;
use Data::Dumper;
use List::Util 'max';
my %data;

        open(DATA, "lic.txt") || die("Could not open file!");
        while (<DATA>) {
            my ( $keys, $date, $hr, $min, $value ) =  ( split /\s+/ => $_ )[ 0, 1, 4, 5, 6 ];
            if ( !exists $data{$date}{$hr}{$min} ) {
                $data{$date}{$hr}{$min} = $value;
            }
            else {
               $data{$date}{$hr}{$min} += $value;
            }
        }
        print sprintf "%s\t%2s\n", "Date/Hours", join( "   " => 0 .. 23 ), $/;
        for my $key ( sort keys %data ) {

                my $max = $data{each %{$data{$key} }};
                $data{$key}{$_} > $max and $max = $data{$key}{$_} for keys %{ $data{$key} };
                print $key, "\t\t",$max;
                }
                print Dumper(%data);

Data:

Loc     Date    Type    Server      Hr  Min Value
EMEA    1-Sep   TYPE-A  Server-A    00  05  4
EMEA    1-Sep   TYPE-A  Server-B    00  05  4
EMEA    1-Sep   TYPE-A  Server-A    00  10  15
EMEA    1-Sep   TYPE-A  Server-B    00  10  15
EMEA    1-Sep   TYPE-A  Server-A    00  15  4
EMEA    1-Sep   TYPE-A  Server-B    00  15  4
EMEA    1-Sep   TYPE-A  Server-A    01  05  5
EMEA    1-Sep   TYPE-A  Server-B    01  05  5
EMEA    1-Sep   TYPE-A  Server-A    01  10  25
EMEA    1-Sep   TYPE-A  Server-B    01  10  25
EMEA    1-Sep   TYPE-A  Server-A    01  15  5
EMEA    1-Sep   TYPE-A  Server-B    01  15  5
EMEA    1-Sep   TYPE-A  Server-A    02  05  35
EMEA    1-Sep   TYPE-A  Server-B    02  05  35
EMEA    1-Sep   TYPE-A  Server-A    03  05  25
EMEA    1-Sep   TYPE-A  Server-B    03  05  15
EMEA    2-Sep   TYPE-A  Server-A    00  05  4
EMEA    2-Sep   TYPE-A  Server-B    00  05  4
EMEA    2-Sep   TYPE-A  Server-A    01  05  5
EMEA    2-Sep   TYPE-A  Server-B    01  05  5
EMEA    2-Sep   TYPE-A  Server-A    02  05  15
EMEA    2-Sep   TYPE-A  Server-B    02  05  15

Edited 1 Year Ago by vivek.vivek

Hi,
You are in the right direction. What output are you having now and what is the new issue?
With a little adjustment to the code we have been using I had this output, which I believe is what you are looking for save the presentation.

$VAR1 = {
          '1-Sep' => {
                       '00' => {
                                 '05' => 8,
                                 '10' => 30,
                                 '15' => 8
                               },
                       '01' => {
                                 '05' => 10,
                                 '10' => 50,
                                 '15' => 10
                               },
                       '02' => {
                                 '05' => 70
                               },
                       '03' => {
                                 '05' => 40
                               }
                     },
          '2-Sep' => {
                       '00' => {
                                 '05' => 8
                               },
                       '01' => {
                                 '05' => 10
                               },
                       '02' => {
                                 '05' => 30
                               }
                     }
        };

Once, you have this the what remains is just presentation.

Hi,

yes, I am stuck there.

My dumper output is as above. The code is

open(DATA, "lic_1.txt") || die("Could not open file!");
        while (<DATA>) {
            my ( $key, $date, $hr, $min, $value ) =  ( split /\s+/ => $_ )[ 0, 1, 4, 5, 6 ];
            if ( !exists $data{$date}{$hr}{$min} ) {
                $data{$date}{$hr}{$min} = $value;
            }
            else {
               $data{$date}{$hr}{$min} += $value;
            }
        }
        print sprintf "%s\t%2s\n", "Date/Hours", join( "   " => 0 .. 23 ), $/;
        foreach my $line (keys %data) {
            my $max = $data{each %{$data{$line} }};
            foreach my $elem (keys %{$data{$line}}) {
                foreach my $elem1 (keys %{$data{$line}{$elem}}) {
                    my $val = $data{$line}{$elem}->{$elem1};
                    $val > $max and $max = $val for keys %{ $data{$line} };
                }
                print "$line   $max\n";
            }
        }
        print Dumper(%data);

So, obviously the issue here is presentation,
below is how I did that.

This is how am getting my data: Since, the name of the station is not an issue i ignore that

while (<DATA>) {
    my ( $date, $hr, $min, $value ) =
      ( split /\s+/ => $_ )[ 1, 4, 5, 6 ];
    if ( !exists $data{$date}{$hr}{$min} ) {
        $data{$date}{$hr}{$min} = $value;
    }
    else {
        $data{$date}{$hr}{$min} += $value;
    }
}

Notice that am using [1, 4, 5, 6] instead of [0, 1, ...]. Other code are the same.

You might have to learn how to use map function in perl.
And just like you rightly pointed out instead of writing a max subroutine used max from List::util.

This is how the presentation goes for me:

print sprintf "%s\t%2s\n", "Date/Hours", join( "   " => 0 .. 23 ), $/;

for my $key ( sort { $a cmp $b } keys %data ) {
    print $key, "\t\t";
    for my $sec_key ( sort keys %{ $data{$key} } ) {
        print max (
            map { $data{$key}{$sec_key}{$_} }
            sort keys %{ $data{$key}{$sec_key} }
          ),
          "  ";
    }
    print $/;
}

Please check the way I use the max to get all the values need for a particular hour and mins, then got the max out of them. Of course, foreach loop can also be used.

my output is like thus:

Date/Hours  0   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23
1-Sep       30  50  70  40  
2-Sep       8  10  30  

I also need to point out that, you should consider using three arugment open function. Do perldoc -f open from your CLI and see what am talking about.

One quick question.

If i add one more field after Value, say "Max". How can I get the table pronted with the sum of Max like "value" column?

Loc    Date     TYPE    Server  Hour  Val   Max
EMEA    1-Sep   TYPE-A  Server-A    00  4   5
EMEA    1-Sep   TYPE-A  Server-B    00  4   5
EMEA    1-Sep   TYPE-A  Server-A    01  5   5
EMEA    1-Sep   TYPE-A  Server-B    01  5   5
EMEA    1-Sep   TYPE-A  Server-A    02  15  15
EMEA    1-Sep   TYPE-A  Server-B    02  15  15
EMEA    2-Sep   TYPE-A  Server-A    00  4   15
EMEA    2-Sep   TYPE-A  Server-B    00  4   15
EMEA    2-Sep   TYPE-A  Server-A    01  5   15
EMEA    2-Sep   TYPE-A  Server-B    01  5   15
EMEA    2-Sep   TYPE-A  Server-A    02  15  15
EMEA    2-Sep   TYPE-A  Server-B    02  15  15

Output:

Hours/Date    00    01    02    03    04    05    06    07    08    09    10    11    12    13    14    15    16    17    18    19    20   21    22    23
Sep-1    08/10    10/10    30/30
Sep-2    08/30    10/30    30/30

The Table you presented doesn't say much. How are you getting 08/10? or 30/30?

Where are those values from or for?

08 is the sum of val for the Hour "00" which was already getting. Now I need 10 which is sum of max for the Hour "00".

I tried changing the code, but I am not able to get a max in hash of "00" hour.

I see. Modify your while loop a bit, and the if/else statement in the while loop to take each value and max for each hour separately. Then you can use your foreach loop display your desired result.

Something like this:

while (<DATA>) {
    my ( $date, $hr, $value, $max ) =
      ( split /\s+/ => $_ )[ 1, 4, 5, 6 ];
    if ( !exists $data{$date}{$hr} ) {
        $data{$date}{$hr}{value} = $value || 0;
        $data{$date}{$hr}{max}   = $max   || 0;
    }
    else {
        $data{$date}{$hr}{value} += $value;
        $data{$date}{$hr}{max}   += $max;
    }
}

then the foreach loop will look like so:

for my $key ( sort { $a cmp $b } keys %data ) {
    print $key, "\t\t";
    for my $hr_key ( sort keys %{ $data{$key} } ) {
        print
          join( "/" => $data{$key}{$hr_key}{value}, $data{$key}{$hr_key}{max} ),
          "   ";
    }
    print $/;
}

It is just manupilating what you have perviously.

Hope this helps.

This question has already been answered. Start a new discussion instead.