in reply to Twisted sort requirements

Yes - this is VERY late to this party, but, this code should be relevant for reference.

I liked injunjoel's streightforward code, but I wanted to simplify it, and make special cases stand out. I also dislike handling special cases inside sort routines, because these are called more often than the number of items to be sorted. I also believe I have minimized the number of loops.

The only part I am not happy with is the "Special Marker" that is passed into the sort. That is a compromise made in order to simplify the code:

#!/usr/bin/perl -w use strict; my @things_to_sort = ( { author => 'bart', title => 'skateboarding' }, { author => 'lisa', title => 'postmodernism' }, { author => 'marge', title => 'hairstyles' }, { author => 'lisa', title => 'THIS BOOK FIRST' }, { author => 'homer', title => 'donuts' }, { author => 'lisa', title => 'Eating Veggies' }, { author => 'bart', title => 'coolness' } ); #this begs for a new structure. #lets use a hash. my (%authors_books, $FirstAuth); my $FirstTitle = "THIS BOOK FIRST"; my $Special_Low_Sort_Marker = "0x00" x 100; # A hundred nulls #turn your AoH's into a HoA's #Find first Author #Mark Specially-named books #see perldsc for reference foreach (@things_to_sort){ if ( $_->{title} eq $FirstTitle){ $FirstAuth = $_->{author} ; push @{$authors_books{ $_->{author} }}, $Special_Low_Sort_Marker . $_->{title}; # Special Marker - + Push to top of SORT }else{ push @{$authors_books{ $_->{author} }}, $_->{title}; } } #display the information. if ($FirstAuth){ PrintAuthor($FirstAuth); delete $authors_books{$FirstAuth}; } foreach my $author ( sort keys %authors_books){ PrintAuthor($author); } ######################## sub PrintAuthor{ my $author = shift; print "$author books:\n"; foreach (sort @{$authors_books{$author}}){ s/^$Special_Low_Sort_Marker//; # Remove Special marker print "\t$_\n"; } }
I added an extra data line, to ensure that sorting was alpha, according the OP's spec. The output:
lisa books: THIS BOOK FIRST Eating Veggies postmodernism bart books: coolness skateboarding homer books: donuts marge books: hairstyles
Extending this to allow Multiple "First Authors" is left as an exercise for the reader.

     "For every complex problem, there is a simple answer ... and it is wrong." --H.L. Mencken

Replies are listed 'Best First'.
Re^2: Twisted sort requirements
by johngg (Canon) on Feb 02, 2006 at 15:01 UTC
    Another late one but never mind! I also adopted the extra data line. Then a pass through the data once to find who wrote "THIS BOOK FIRST" and the rest can be done in a Schwartzian transform.
    #!/usr/local/bin/perl -w # use strict; our @thingsToSort = ( {author => 'bart', title => 'skateboarding'}, {author => 'lisa', title => 'postmodernism'}, {author => 'marge', title => 'hairstyles'}, {author => 'lisa', title => 'THIS BOOK FIRST'}, {author => 'homer', title => 'donuts'}, {author => 'bart', title => 'coolness'}, {author => 'lisa', title => 'eating veggies'}); our $firstAuthor = q(); foreach (@thingsToSort) { next unless $_->{title} eq 'THIS BOOK FIRST'; $firstAuthor = $_->{author}; last; } print map {"$_->[0]->{author}: $_->[0]->{title}\n"} sort { $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2] || $a->[0]->{author} cmp $b->[0]->{author} || $a->[0]->{title} cmp $b->[0]->{title} } map { [ $_, $_->{title} eq 'THIS BOOK FIRST', $_->{author} eq $firstAuthor ] } @thingsToSort;
    I tried to think of a way to accomplish the first pass in the transform to make things simpler but failed.

    Cheers,

    JohnGG