Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

detect a letter

Status
Not open for further replies.

Porshe

Programmer
Jun 5, 2001
38
US
Hi everyone! I have a line that looks like this:

report: source-a, name-d, time-a

I need to detect whether it's an -a or -d for ascending or descending. So this is my pseudocode:
#$field1 is source-a

if ($field1 contains -a)
then sort ascending
else sort descending

if it's not clear, I can clarify.

Thanks, Porshe
 
you might use a pattern match.

if ($field1 =~ /-a$/)
{
# do ascending
}
elsif ($field1 =~ /-d$/)
{
# do descending
}


REGEX EXPLAIN:
if ($field1 =[red]~[/red] /-a$/) { do something; }

[red]~[/red] - turns the equal into a pattern match operator
'-a' - your trigger for ascending
/ - delimiters for the pattern to match
$ - pins the pattern to the end of the string that is being searched


HTH


keep the rudder amid ship and beware the odd typo
 
Thanks- it works as this:

if ($field1 =~/-a/) {
@sorted = sort { $a cmp $b } keys %list;
}
elsif ($field1 =~/-d/) {
@sorted = sort {$b cmp $a } keys %list; }

Now I need to do a sort within a sort. If the elements are equal, I need to get the $field2 variable and sort it and if anything is equal it needs to get $field3. I saw this in the cookbook but it doesn't work when I put the $a and $b ->to my $field variables:

@sorted = sort {$a->$field1 cmp $b->$field1
||
$a->$field2 cmp $b->$field1}
keys %list;

Thanks,
Porshe
 
Lets say you have the file containing lines like:

a b x
a b z
a a y
etc...

Then try this:

Code:
while( <> ) {
    chomp;
    @f = split;
    $k{$_} = $_;
    $f0{$_} = $f[0];
    $f1{$_} = $f[1];
    $f2{$_} = $f[2];
}

$cond = &quot;1-a 2-d 3-a&quot;;
@c = split;

sub by_f {
    $s0 = ( $c[0] =~ /-a$/ ?
            $f0{$a} cmp $f0{$b} :
            $f0{$b} cmp $f0{$a} );
    $s1 = ( $c[1] =~ /-a$/ ?
            $f1{$a} cmp $f1{$b} :
            $f1{$b} cmp $f1{$a} );
    $s2 = ( $c[2] =~ /-a$/ ?
            $f2{$a} cmp $f2{$b} :
            $f2{$b} cmp $f2{$a} );

    return ( $s0 || $s1 || $s2 );
}

foreach ( sort by_f keys %k ) {
    print &quot;$_\n&quot;;
}

Sorry for any typos. The copy-paste aint working at the moment, so I typed this in by hand :-(

Hope this helps, s-) NEIL
 
Right now you are sorting the keys from a hash. Where do field2 and field3 come from? Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
fields 2 and 3 are from the input of:

report: source-a, name-d, time-a

so field1 is source in asc. order,
field2 is name in desc. order,
and field3 is time in asc. order.

when source gets sorted first, if there is a match, I want it to sort by name, then if there are any matches sort it by time. Like a sort within a sort.

Thanks,
Portia
 
I guess I'm confused then, where does the hash come from (the one who's keys you're sorting)? Also, can you give us a couple of example lines from the file? Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
here is the data:

report: sort source-a,time-a,port-a
Monmouth,2000-05-2000,192
Jackson,2000-04-2100,167
Monmouth,2000-04-1000,63

so first I want to sort by source so it should be
Jackson,2000-04-2100,167
Monmouth,2000-05-2000,192
Monmouth,2000-04-1000,63
but there are 2 monmouths so I need to sort by time, so it should end up looking like:
Jackson,2000-04-2100,167
Monmouth,2000-04-1000,63
Monmouth,2000-05-2000,192

and if the times where the same then I would sort by port. I just need a sorting routine that would allow me to do sorts then a sort within a sort if there are matching elements.
I hope this is clearer.
Thanks!
Porshe

 
This should work for you. I assumed you wanted to sort by port ascending. If you want descending, swap $data1[2] and $data2[2].
Code:
@newlist = sort mysort @list;
sub mysort($) {
    @data1 = split (/,/,$a);
    @data2 = split (/,/,$b);
    $data1[0] cmp $data2[0] || $data2[1] cmp $data1[1] || $data1[2] <=> $data2[2];
}
 
I threw this together pretty quickly, and I haven't tested it, but I think it will work. Your first task is to get the report record and parse it to find which fields to sort on and in which order, then sort the data. This will do that:
Code:
#!/usr/local/bin/perl

# Table to translate field names to field numbers
%fieldnums = (
   'source' => 1,
   'time' => 2,
   'port' => 3,
);

open(INFILE, $datafile);

my $report_rec = <INFILE>;
my @data_recs = (<INFILE>);

close INFILE;

unless ($report_rec =~ /\Areport:\s+sort\s+(\S*)\Z/) {
   print &quot;Invalid report record\n&quot;;
   exit 1;
}
# $1 now contains the sort params

my @sort_params = split(/,/, $1);
# figure out which seqence to sort in
foreach my $sort_param (@sort_params) {
   ($fieldname,$seq) = split(/-/, $sort_param);
   push(@sortfields, $fieldnums{$fieldname});
   push(@sortseqs, $seq);
}

my @sorted_data = sort SortRtn @data_recs;

foreach my $data_rec (@sorted_data) {
   ($source,$time,$port) = split(/,/, $data_rec);
   print &quot;Source: $source, Time: $time, Port:$port\n&quot;;
}

exit 0;

sub SortRtn {
   my(@a) = split(/,/, $a);
   my(@b) = split(/,/, $b);

   # step thru the sort fields
   foreach my $fldnum (0..$#sortfields) {
      if ( $sortseq[$fldnum] eq 'a' ) {
         $compare = $a[$fldnum] cmp $b[$fldnum];
      } else {
         $compare = $b[$fldnum] cmp $a[$fldnum];
      }
      if ( $compare ) { #fields did not compare equal
         return $compare;
      }
   }

   # If we get this far, all fields are equal
   return 0;
}

1;
Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top