http://qs1969.pair.com?node_id=90970

I log all incoming connections to my opennap server to a postgres database. I get about 625,000 connections per day, and I wanted to sort them by domain so that I could see visually in text where they were coming from. So I'll spare you the database calls. This, however, was a cool little hack to print the hosts out sorted by domain (rather than hostname). You can easily use File::Slurp to write the scalar obtained.

Credit to risacher for the sprintf right-justify.

my $noodle = join "$/", map { sprintf "%64s", $_ } ( sort { reverse($a +) cmp reverse($b) } (keys %hosts) );

Replies are listed 'Best First'.
Re: Sort a long list of hosts by domain
by japhy (Canon) on Jun 23, 2001 at 20:42 UTC
    I have a feeling this has a speed increase. It's a Guttman-Rosler Transform, which means that the sorting is done by the native sort(). Also, I only reverse each key twice, whereas your method is probably doing a lot more reversing.
    @by_domain = map { scalar reverse } sort map { scalar reverse } keys %hosts;


    japhy -- Perl and Regex Hacker
      How about a pointer to Guttman-Rosler Transform, or a list of such transforms in general? I assume this will be in your book?
        My book is regex-related. Uri Guttman and/or Larry Rosler has information about the GRT; try this URL. I do have some sorting stuff online at my web site.

        japhy -- Perl and Regex Hacker
Re: Sort a long list of hosts by domain
by Brovnik (Hermit) on Jun 24, 2001 at 00:18 UTC
    This is perfect for the Schwartzian Transform.
    my @sorted = map { $_->[1] } sort { $a->[0] cmp $b->[0] } map { [join('.',reverse split(/\./)),$_] } @unsorted;
    or, to put it into the form you provided,
    my $noodle = join($/, map { sprintf("%64s",$_->[1]) } sort { $a->[0] cmp $b->[0] } map { [join('.',reverse split(/\./)),$_] } keys %hash );
    Update: to point to merlyn's original post.
    --
    Brovnik
Re: Sort a long list of hosts by domain
by mdillon (Priest) on Jun 23, 2001 at 21:18 UTC
    i'm not sure i agree that you are sorting by domain. domains are grouped, but the overall order of the result is strange. however, i think the following sub does what most people would expect:
    sub sort_domains { map { ${$_->[0]} } sort { my ($pa, $pb, $rv) = ($#{$a->[1]}, $#{$b->[1]}, 0); do { $rv ||= $a->[1][$pa] cmp $b->[1][$pb] } while (!$rv and $pa-- and $pb--); $rv ||= ($pb >= 0) ? -1 : ($pa >= 0) ? 1 : 0; } map { [ \$_, [ split /\./, $_ ] ] } @_ }
    you can use it like so: my $noodle = join $/, map { sprintf "%64s", $_ } sort_domains keys %hosts;

    p.s. let the golf begin

    p.p.s. why $noodle?

    update: fixed logic bug in line that deals with extra domain parts ($rv ||= ($pb >= 0) ? -1…)