Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Hash of Arrays Sorting Problem

by Anonymous Monk
on Oct 29, 2002 at 20:10 UTC ( [id://208856]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have an Array of Hashes (at least I think that's what it is) containing the following data structure:

{$sorter}
 {$domain}
  {$time}

Basically, each sorter can have multiple domains and each domain can have multiple times, and domains and times can be repeated.

foreach $sorter (keys %hash) { print "\n\nSORTER=$sorter"; foreach $domain (keys %{$hash{$sorter}}) { foreach $time (@{$hash{$sorter}{$domain}}) { print "\nDomain=$domain, Time=$time"; } }
I am trying to print the Domain=$domain, Time=$time line sorted by the ascending value of $time for the top "X" number of time values.

Can anyone help me out?

Replies are listed 'Best First'.
(tye)Re: Hash of Arrays Sorting Problem
by tye (Sage) on Oct 29, 2002 at 21:16 UTC

    Here is what I think is a simple approach that is easy to maintain:

    foreach my $sorter ( keys %hash ) { print "\n\nSORTER=$sorter"; my @time; foreach my $domain ( keys %{$hash{$sorter}} ) { foreach my $time ( @{$hash{$sorter}{$d­omain}} ) { push @time, "$time $domain" . "\nDomain=$domain, Time=$time"; } } foreach my $line ( sort @time ) { my $output= ( split /\n/, $line, 2 )[1]; print $/, $output; } }
    You create a list of strings, each one starts with a string built such that the default sort will put them in the order that you want...

    I'm assuming your "time" has leading zeros and fields order from largest to smallest (days before hours before minutes before seconds, for example) so that no reformatting is required, and that you'd like to sort within duplicate times based on domain. So this part is simply "$time $domain".

    After that part, put a delimiter and the value you want to get in the end. The "\n" you already had at the front of your desired result makes a fine delimiter.

    Then sort your list. Throw away the first part of each string and print out the last part.

            - tye
Re: Hash of Arrays Sorting Problem
by gjb (Vicar) on Oct 29, 2002 at 20:38 UTC

    If I understand your data structure, you could do it the following way.

    #!perl use strict; my %data = ( 'sort 1' => {'a.b.c' => ['19:20', '20:30'], 'a.b.d' => ['15:10', '19:40']}, 'sort 2' => {'e.f.g' => ['12:13'], 'g.h.i' => ['8:15', '23:11']}); my %times; foreach my $sorter (values %data) { foreach my $domain (keys %$sorter) { foreach my $time (@{$sorter->{$domain}}) { push(@{$times{$time}}, $domain); } } } foreach my $time (sort { cmpTime($a, $b) } keys %times) { foreach my $domain (@{$times{$time}}) { print "domain: $domain, time: $time\n"; } } sub cmpTime { my ($t1, $t2) = @_; my ($h1, $m1) = split(/:/, $t1); my ($h2, $m2) = split(/:/, $t2); return 60*$h1 + $m1 <=> 60*$h2 + $m2; }

    Of course, you'd have to adapt cmpTime to reflect the format your time stamps are in.

    Hope this helps, -gjb-

Re: Hash of Arrays Sorting Problem
by kabel (Chaplain) on Oct 29, 2002 at 20:22 UTC
    perhaps this gets you started:
    use strict; use warnings; my %hash = ( sorter1 => { domain1 => [ 123, 124, 112, 110, ], }, ); foreach my $sorter (keys %hash) { print "\n\nSORTER=$sorter"; foreach my $domain (keys %{$hash{$sorter}}) { my $current = 0; my $show_max = 2; foreach my $time (reverse sort @{$hash{$sorter}{$domain}}) { print "\nDomain=$domain, Time=$time"; (++ $current >= $show_max) and last; } } }

    always use strict and warnings. you can dump arbitrary data structures with the Data::Dumper module.
    use Data::Dumper; print Dumper \%hash;
      The problem I run into with this approach is the times are sorted by domain. When the domain changes, the time sorting starts all over again. In other words, output could be as follows:

      Sorter=John.Doe
      Domain=domain1.com, Time=1000
      Domain=domain1.com, Time=1001
      Domain=domain1.com, Time=1003
      Domain=domain2.com, Time=1002
      Domain=domain2.com, Time=1003

      I need all domains sorted according to ascending time
        sorry, i had an incorrect understanding about your question.
        done better below.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://208856]
Approved by VSarkiss
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (8)
As of 2024-03-28 19:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found