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

Hail fellow monks, It seems that I need to come for your sage advice once again. I have a record that I read into a bunch of arrays.
(@array1, @array2, @array3, ...)= split;
Now $array1[0] and $array2[0] and $array3[0] and ... all reference different fields in the same record. The fields vary as to type and length. What I need to do is sort any one of the fields and then display all fields associated with that sorted field. I thought that I could create an index with the following code, but it doesn't seem to work that way. Also, not all the fields are unique, so how do you allow for double records in the sorted file and still keep them associated with the same record in the unsorted file.
sub Sort_File { my @Sort_by = @_; @sorted_array = sort { $a <=> $b || $a cmp $b } Sort_by; for ($x = 0; $x <= @sorted_array; $x++){ for ($y = 0; $y <= @sorted_array; $y++){ if ( $sorted_array[$x] == $Sort_by[$y]) { $index[$x] = $y; print $index[$x],"\n"; } } }
Thanks in advance! Prince99

Too Much is never enough...

Replies are listed 'Best First'.
Re: Sorting arrays and maintaining an index
by Masem (Monsignor) on Apr 12, 2001 at 21:21 UTC
    Would not:
    @arrays = sort { $a->[$y] cmp $b->[$y] } @arrays;
    do the trick, where @arrays is an array of references to the arrays you want to sort?
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: Sorting arrays and maintaining an index
by suaveant (Parson) on Apr 12, 2001 at 21:29 UTC
    You could do the following...
    for(my $i = 0; $i <= $#Sort_by; $i++) { push @{$sort{$Sort_by[$i]}} = $i; } for $key (sort { sort code } keys %sort) { for(@{$sort{$key}}) { print "Index: $_ - Data: $key\n"; } }
    so you can keep the index even if the data is the same, you could also lowercase the data in the hash keys and grab the original data out of the original array with the index value. The secret is push the values onto the hash as an array, so you get all your dupes...

    I'm not sure if that's what you want or not
                    - Ant

Re: Sorting arrays and maintaining an index
by satchboost (Scribe) on Apr 12, 2001 at 21:28 UTC
    The first thing I note is that your method doesn't handle double-entries. The first entry found with that value will be the one used.

    One question I'd have is if you need to maintain the initial ordering. If you don't, you could build some sort of Schwartzian transform and move the cross-array slices around that way.

    A deeper question would be if parallel arrays are really what you want to do. Anytime I see parallel arrays, especially in Perl, I start itching to offer up possible better solutions. For example, you have a record. Whenever I hear "record", I immediately think "hash". They're built for storing records. Then, you have a list of hashrefs for your various records. If you need to print out all of a given field, then iterate over the array.

    The reason I suggest this is that sorting this list of hashrefs becomes trivial.

    @sorted_list = sort {$a->{Field} <=> $b->{Field} || $a->{Field} cmp $b->{Field}} @unsorted_list
    And, double-entries are automatically taken care of. Plus, you can now do multi-level sorts. Sort on state, then town, or whatever.
      Unfortunately I do have to keep the original order. I have written a script that puts the values into a hash, and even sorts based on numeric vs. lexical. I just don't understand the hash enough to grab info as needed. Here is my other code if it helps. Sorry it is long.
      use strict; use vars qw(@Claim_Fields %Claim_Table); my $data_file = "/where/the/file/is"; @Claim_Fields = ( [ 'claim_batch_number', 'N', 'A8' ], [ 'claim_number', 'N', 'A6' ], [ 'claim_type', 'L', 'A2'], [ 'payment_direct', 'N', 'A2'], [ 'pharmacy_number', 'N', 'A6'], [ 'chain_number', 'N', 'A4'], [ 'pharmacy_name', 'L', 'A30'], [ 'reject_code_1', 'N', 'A4'], [ 'reject_code_2', 'N', 'A4'], [ 'rx_number', 'N', 'A8'], ...#many more fields follow); %Claim_Table = get_table(); Main: { my $sort_by = $ARGV[0]; open(CLAIMS, $data_file) or die "CANNOT OPEN FILE: $!"; my @claim_records = (); while (<CLAIMS>) { my $x = $_; while(length($x gt 0)) { $_ = substr($x, 0, 434); $x = substr($x, 434); push(@claim_records, read_record($_)); } } close(CLAIMS); &Sort_File($sort_by, @claim_records); } sub Sort_File { my ($sort_by, @claim_records) = @_; my $sort_sub; # If the sorting type is numeric if ( $Claim_Table{$sort_by} eq 'N' ) { # Create sub for numeric sort $sort_sub = sub { $a->{$sort_by} <=> $b->+ $sort_by} }; } # End if numeric # Otherwise it's lexical else { # Create sub for lexical sort $sort_sub = sub { $a->{$sort_by} cmp $b-> +{$sort_by} }; } foreach my $record ( sort $sort_sub @claim_records ) { print STDOUT $record->{$sort_by}, "\n"; } } sub read_record { my ($line) = @_; my %claim_record = (); @claim_record{ get_fields() } = unpack( get_template(), $line); return \%claim_record; } sub get_fields { my @fields = (); foreach my $claim_field ( @Claim_Fields ) { push(@fields, $claim_field->[0]); } return @fields; } sub get_template { my $template = ''; foreach my $claim_field ( @Claim_Fields ) { $template .= $claim_field->[2]; } return $template; } sub get_table { my %table = (); foreach my $claim_field ( @Claim_Fields ) { $table{$claim_field->[0]} = $claim_field->[1]; } return %table; }
      This creates the hash and sorts by whatever field is entered on the command line, but that is where I get lost. I don't know how to get to the correct associated fields. Prince99

      Too Much is never enough...