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

Good day Monks, Here's my problem.
I have a text file with content
name=Document1.doc type=Word author=aAuthor name=Document1.doc type=Excel author=bAuthor name=Document1.doc type=Text author=cAuthor name=Document1.doc type=Excel author=dAuthor name=Document1.doc type=Word author=eAuthor
My problem is to sort this file and write to another (first based on the key "type" and then on the key "author") so that the output file looks like :
name=Document1.doc type=Excel author=bAuthor name=Document1.doc type=Excel author=dAuthor name=Document1.doc type=Text author=cAuthor name=Document1.doc type=Word author=aAuthor name=Document1.doc type=Word author=eAuthor
What I have tried is to write a function which accepts one key name and sort the file based on that key. Again the function will be invoked with the second key. But when I invoked the function with second key, the output happened to be sorted in second key alone(the first level sorting has gone which is obvious). Is there any way with which I can do this in one stretch.?
Any suggestions welcome.
#$field is the position of the element (sort key) in the #line open INPUT , $input || die $input.$! ; while (<INPUT>) { @fields = split(" ",$_) ; push @{$hash{$fields[$field]}}, $_ ; $hash_keys{$fields[$field]} = $fields[$field] unless exists $h +ash_keys{$fields[1]} ; } for $element (sort keys %hash_keys) { open OUTPUT, ">>$output" || $output.$! ; print OUTPUT @{$hash{$element}} ; close OUTPUT ; } close INPUT ;
Many thanks for your time..

Replies are listed 'Best First'.
Re: Sorting with multiple keys
by salva (Canon) on Feb 03, 2006 at 08:21 UTC
    you can use Sort::Key to generate fast multikey sorting functions:
    # Create a keysort function that uses two strings as keys: use Sort::Key::Maker ss_keysort => qw(string string); # And then use it. # The first argument passed is the subroutine # to extract the keys from the data: my @sorted_by_type_and_author = ss_keysort { /^name=.*? type=(.*?) author=(.*?)$/; ($1, $2) } @lines;
Re: Sorting with multiple keys
by GrandFather (Saint) on Feb 03, 2006 at 07:23 UTC

    Here's a starting point:

    use strict; use warnings; my @rows; push @rows, [split ' '] while <DATA>; print "@$_\n" for sort {$a->[1] cmp $b->[1] or $a->[2] cmp $b->[2]} @r +ows; __DATA__ name=Document1.doc type=Word author=aAuthor name=Document1.doc type=Excel author=bAuthor name=Document1.doc type=Text author=cAuthor name=Document1.doc type=Excel author=dAuthor name=Document1.doc type=Word author=eAuthor

    Prints:

    name=Document1.doc type=Excel author=bAuthor name=Document1.doc type=Excel author=dAuthor name=Document1.doc type=Text author=cAuthor name=Document1.doc type=Word author=aAuthor name=Document1.doc type=Word author=eAuthor

    DWIM is Perl's answer to Gödel
Re: Sorting with multiple keys
by BrowserUk (Patriarch) on Feb 03, 2006 at 07:34 UTC

    [0] Perl> @toSort = split "\n", <<'END'; name=Document1.doc type=Word author=aAuthor name=Document1.doc type=Excel author=bAuthor name=Document1.doc type=Text author=cAuthor name=Document1.doc type=Excel author=dAuthor name=Document1.doc type=Word author=eAuthor END ;; Perl> print for map{ $_->[0] } sort{ $a->[1] cmp $b->[1] } map{ [ $_, join'', m[type=(\S+)\s+author=(\S+)] ] } @toSort;; name=Document1.doc type=Excel author=bAuthor name=Document1.doc type=Excel author=dAuthor name=Document1.doc type=Text author=cAuthor name=Document1.doc type=Word author=aAuthor name=Document1.doc type=Word author=eAuthor

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Sorting with multiple keys
by Mandrake (Chaplain) on Feb 06, 2006 at 05:05 UTC
    All, Thanks for solutions..