in reply to Sorting arrays and maintaining an index

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.

Replies are listed 'Best First'.
Re: Re: Sorting arrays and maintaining an index
by Prince99 (Scribe) on Apr 12, 2001 at 22:07 UTC
    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...