http://qs321.pair.com?node_id=189464

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

I'm trying to sort data coming from file. 1st file has
words that are in specific order like this: (not alphabetic)

GAVSTE
GAVARC
GAVADA
GAVIMM
GAVSP.
add so on...

It is "order quide" for sorting

2nd file in flatfile (delimiter is "|"):

GAVARC 10.3. Tahkoluoto 1m
SOMMOL 10.3. Tahkoluoto 7m
GAVSTE 7.4. Preiviiki 1p
GAVARC 7.4. Preiviiki 2p
SOMMOL 16.3. Kallo 6m

Printig should look like this:
GAVSTE 7.4. Preiviiki 1p
GAVARC 10.3. Tahkoluoto 7m
GAVARC 7.4. Preiviiki 1p
SOMMOL 10.3. Tahkoluoto 7m
SOMMOL 16.3. Kallo 6m
Is this possible at all?

PH
ps. Hope it's readable now

Replies are listed 'Best First'.
Re: Sorting with perl
by Abigail-II (Bishop) on Aug 12, 2002 at 13:00 UTC
    #!/usr/bin/perl use 5.8.0; use strict; use warnings 'all'; use sort 'stable'; my ($first, $second) = @ARGV; open my $fh => $first or die "open first: $!\n"; chomp (my @words = <$fh>); close $fh; my $c = 0; my %words = map {$_ => ++ $c} @words; open my $sh => $second or die "open second: $!\n"; my @info; while (<$sh>) { chomp; push @info => [split /\|/]; } close $sh; @info = sort {$words {$a -> [0]} <=> $words {$b -> [0]}} @info; print "@$_\n" for @info; __END__
    Give the names of the two files as arguments. And if there's a lot of data, you may want to turn the sort into a GRT.

    Abigail

      Well, if you think the same, i can't be too wrong ;)

      --
      http://fruiture.de
        The example given suggests he wanted a stable sorting, hence my "use sort 'stable'". Your code only gives a stable sorting because that happens to be the default on 5.8.0, but that may change in a future version of perl (and if a sort happens to be stable in pre-5.8.0, it's just a coincidence).

        Abigail

Re: Sorting with perl
by RMGir (Prior) on Aug 12, 2002 at 13:06 UTC
    (Edit: See Sorting with perl for a reformatted version of the question, and other answers).

    I'm going to try to answer your question, but it would have been easier if you'd used the <code> and a few <p>aragraph tags to make it more readable. Please check out Writeup Formatting Tips.

    1st file has words that are in specific order like this: (not alphabetic) GAVSTE GAVARC GAVADA GAVIMM GAVSP

    So you open up the first file, and read it into a hash that defines the sort order: (I'm assuming there's newlines between the words in the first file)

    #/usr/bin/perl -w use strict; my %sortOrder; # replace "file1" with the filename of the first file my $currentOrder=0; open(FILE1,"<file1") or die "Can't open 'file1', error $!"; while(<FILE1>) { chomp; # associate the current word with its place in the sort order $sortOrder{$_}=$currentOrder++; } close(FILE1);
    It is "order quide" for sorting 2nd file in flatfile (delimiter is "|"): GAVARC 10.3. Tahkoluoto 1m SOMMOL 10.3. Tahkoluoto 7m GAVSTE 7.4. Preiviiki 1p GAVARC 7.4. Preiviiki 2p SOMMOL 16.3. Kallo 6m

    I have to guess at where the newlines are, so I'm going to assume the 2nd file looks like:

    GAVARC|10.3.|Tahkoluoto|1m SOMMOL|10.3.|Tahkoluoto|7m GAVSTE|7.4.|Preiviiki|1p GAVARC|7.4.|Preiviiki|2p SOMMOL|16.3.|Kallo|6m
    (continued from previous code:)

    my @data; open(FILE2,"<file2") or die "Can't open 'file2', error $!"; while(<FILE2>) { chomp; my ($keyField)=split /\|/,$_; die "Don't have a sort key for $keyField" unless exists $sortOrder +{$keyField}; # push in a reference to an array where the first # element is the sort order. This is the Scwartzian # transform sorting method push @data,[$sortOrder{$keyField},$_]; } close(FILE2); my @sorted=map {pop @$_} sort {$a->[0] <=> $b->[0]} @data; # I'm assuming you want the | delimiters in the output? print join "\n", @sorted;
    For more details see Schwartzian Transform. A higher performance approach is the Guttman Rosler Transform but it's a bit more complicated to follow.
    --
    Mike
Re: Sorting with perl
by demerphq (Chancellor) on Aug 12, 2002 at 12:49 UTC
    This is possible. Although its is somewhat difficult to say how without a clearer idea of what you want. Try to put together a solution and then post it and im sure the monks at large will show you where you have gone wrong. Also please read the markup gidlines for the site. Your mail is particularly difficult to understand because it is so poorly formatted.

    Yves / DeMerphq
    ---
    Software Engineering is Programming when you can't. -- E. W. Dijkstra (RIP)

Re: Sorting with perl
by fruiture (Curate) on Aug 12, 2002 at 13:09 UTC

    Use a Hash!

    #!/usr/bin/perl use strict; use warnings; my $guidefile = './guide'; my $flatfile = './flat'; my $delimiter = qr{\s*\|\s*}; my (%guide,@flat); open GUIDE,'<',$guidefile or die "E: open($guidefile): $!"; {my $i = 0; while(<GUIDE>){ chomp; $guide{$_}=$i++ } } close GUIDE; open FLAT,'<',$flatfile or die "E: open($flatfile): $!"; while( <FLAT> ){ chomp; push @flat,[split /$delimiter/]; } close FLAT; foreach( sort { ($guide{ $b->[0] }||0) <=> ($guide{ $a->[0] }||0) } @ +flat ){ print join("\t", exists($guide{$_->[0]}) ? $guide{$_->[0]} : '-', @$_),"\n"; }
    --
    http://fruiture.de
Re: Sorting with perl
by I0 (Priest) on Aug 13, 2002 at 07:35 UTC
    open F1,"<1st.file" or die "can't open 1st.file: $!"; chomp(my @order = <F1>); close F1; my $c = 'a'x (1+(log @order)/3); my %order = map {$_ => ++$c} @order; open F2,"<2nd.file" or die "can't open 2nd.file: $!"; print map{/\|(.*)/s} sort map{$order{(/([^|]*)/)[0]}."|$_"} <F2>; close F2;