in reply to Use a hashref as a key in another hashref?

For interest the same task using a database could look like the following:

use strict; use warnings; use DBI; my @date = qw(year month day hour minute); my @items = qw(burgers fries sodas); my @fields = (@date, @items); my @entries = ( makeEntry( 'day' => 1, 'month' => 1, 'year' => 2000, 'hour' => 4, 'minute' => 44, 'burgers' => 5, 'fries' => 3, 'sodas' => 11 ), makeEntry( 'day' => 1, 'month' => 1, 'year' => 2000, 'hour' => 4, 'minute' => 45, 'burgers' => 2, 'fries' => 4, 'sodas' => 7 ), ); unlink 'delme.sqlite'; my $dbh = DBI->connect("dbi:SQLite:dbname=delme.sqlite","",""); my $sql = <<SQL; CREATE TABLE Sales ( year INTEGER, month INTEGER, day INTEGER, hour INTEGER, minute INTEGER, burgers INTEGER, fries INTEGER, sodas INTEGER ) SQL $dbh->do ($sql); my $columns = join ', ', @fields; my $places = join ', ', ('?') x @fields; my $sth = $dbh->prepare ("Insert INTO Sales ($columns) VALUES ($places +)"); $sth->execute(@$_) for @entries; $sth = $dbh->prepare("select * from Sales order by Year, Month, Day, H +our, Minute"); $sth->execute(); while (my $row = $sth->fetchrow_hashref()) { printf "%04d/%02d/%02d %02d:%02d:00\n", @{$row}{@date}; printf " %-7s %s\n", $_, $row->{"${_}"} for @items; } sub makeEntry { my %row = @_; return [@row{@fields}]; }

Prints:

2000/01/01 04:44:00 burgers 5 fries 3 sodas 11 2000/01/01 04:45:00 burgers 2 fries 4 sodas 7

But now that you have the data in a database you have much better options for extracting interesting information. For example, you can now order the output by, say, soda sales with a simple change to the select (select * from Sales order by fries desc, Year, Month, Day, Hour, Minute) or look at sales during a particular time each day (select * from Sales Where minute = 45).

Perl is the programming world's equivalent of English

Replies are listed 'Best First'.
Re^2: Use a hashref as a key in another hashref?
by poj (Abbot) on Jun 05, 2014 at 12:20 UTC
    Or 'Relational' like this perhaps
    #!perl use strict; use warnings; use DBI; #create db my $dbfile = 'database.sqlite'; unlink($dbfile); my $dbh = DBI->connect('dbi:SQLite:dbname='.$dbfile , undef , undef , {RaiseError =>1, AutoCommit =>0}) or die $DBI::errstr; $dbh->do('CREATE TABLE STATS (ID integer, DTIME time, PRIMARY KEY (ID))'); $dbh->do('CREATE TABLE SALES (ID integer, PRODUCT, VOLUME integer, PRIMARY KEY (ID,PRODUCT))'); $dbh->do('CREATE TABLE PRODUCT (PRODUCT, SECTOR, PRIMARY KEY (PRODUCT))'); $dbh->commit; # load data my $sth = $dbh->prepare('INSERT INTO STATS VALUES (?,?)'); while (<DATA>){ chomp; last if $_ eq 'PRODUCT'; my ($id,@f) = split ','; my $dt = sprintf "%04d-%02d-%02d %02d:%02d:00",@f[2,1,0,3,4]; $sth->execute($id,$dt) if ($id); print "STATS INSERT $id,$dt\n"; } $dbh->commit; $sth = $dbh->prepare('INSERT INTO PRODUCT VALUES (?,?)'); while (<DATA>){ chomp; last if $_ eq 'SALES'; my (@f) = split ','; $sth->execute(@f) if (@f==2 ); print "PRODUCT INSERT @f\n"; } $dbh->commit; $sth = $dbh->prepare('INSERT INTO SALES VALUES (?,?,?)'); while (<DATA>){ chomp; my (@f) = split ','; $sth->execute(@f) if (@f==3); print "SALES INSERT @f\n"; } $dbh->commit; # report Sales in Sector By Year print "\n"; my $sql = "SELECT strftime('%Y',DTIME) as year,SECTOR,SUM(VOLUME) AS t +otal FROM SALES AS sa LEFT JOIN STATS AS st ON sa.ID = st.ID LEFT JOIN PRODUCT AS pr ON sa.PRODUCT = pr.PRODUCT GROUP BY year,SECTOR ORDER BY total"; my $ar = $dbh->selectall_arrayref($sql); print "REPORT\n"; printf "%4s %-10s %6s\n",qw(Year Sector Volume); printf "---- ---------- ------\n"; for (@$ar){ printf "%4d %-10s %6d\n",@$_; } __DATA__ 1,1,1,2000,4,44 2,1,1,2000,4,45 PRODUCT burgers, food fries, food sodas, drink SALES 1,burgers,5 1,fries,3 1,sodas,11 2,burgers,2 2,fries,4 2,sodas,7

    Produces

    REPORT Year Sector Volume ---- ---------- ------ 2000 food 14 2000 drink 18
    poj