in reply to Complex sorting and counting question.

What part of the answer you got in Revisiting the "Getting top x matches" thread do you have problems with? Maybe you can show us some more code and detail where exactly your code returns the wrong results. Also see Counting events and getting top 5 matches, which treats a problem not entirely dissimilar to your problem.

  • Comment on Re: Complex sorting and counting question.

Replies are listed 'Best First'.
Re^2: Complex sorting and counting question.
by nefertiti (Initiate) on Sep 19, 2008 at 02:19 UTC
    Hi Monks, Below is the code provided by someone. What I do'nt get is the %code = map onwards. I'm not sure what's he's trying to get. I have difficulty understanding this part. Thanks for the help.
    my $query = $db->prepare("select code, username, userid from transacti +ons"); $query->execute(); my %code = map { $_ => [] } 0 .. 13; while (my $r = $qeury->fetchrow_hashref()) { my $c = $$r{code}; push @{$code{$c}}, $r; } # For each code $c, $code{$c} is now an arrayref which # contains the relevant records (as hashrefs). The # number of elements in the array equals the number # of occurances. Now, for the second part... my %topfive; for my $c (keys %code) { my %user; for my $row (@{$code{$c}}) { # Note: this assumes that the userid field # is unique to each user. $user{$$row{userid}}{count}++; $user{$$row{userid}}{name} = $$row{username}; } $topfive{$c} = [(sort { $$b[2] <=> $$a[2] } map { [$_, $user{$_}{name}, $user{$_}{count}] } keys %user)[0 .. 4]]; }

      Maybe you should ask the monk who wrote it directly then? That's why we have threaded replies here. Anyway:

      This prepares and executes an SQL statement, see DBI:

      my $query = $db->prepare("select code, username, userid from transacti +ons"); $query->execute();

      This initializes the %code hash with the keys from 0 to 13. See perlop about the range operator, map and then Data::Dumper for how to inspect data structures.

      my %code = map { $_ => [] } 0 .. 13;

      This line contains a typo that use strict; will catch for you. See strict and likely then Coping with Scoping.

      while (my $r = $qeury->fetchrow_hashref()) {

      This loop overall fetches each retrieved hash and puts it into the corresponding array in %code:

      my $c = $$r{code}; push @{$code{$c}}, $r; } # For each code $c, $code{$c} is now an arrayref which # contains the relevant records (as hashrefs). The # number of elements in the array equals the number # of occurances. Now, for the second part...

      This code determines the top five userids.

      my %topfive; for my $c (keys %code) { my %user; for my $row (@{$code{$c}}) { # Note: this assumes that the userid field # is unique to each user. $user{$$row{userid}}{count}++; $user{$$row{userid}}{name} = $$row{username}; } $topfive{$c} = [(sort { $$b[2] <=> $$a[2] } map { [$_, $user{$_}{name}, $user{$_}{count}] } keys %user)[0 .. 4]]; }

      I already recommended pushing more work back into the database instead of manually sorting and counting.