--- Roy Peters <[EMAIL PROTECTED]> wrote:
> hi,
> 
> I have the following string 
> 
> $a = 
> "buy 10/23/01 100 12.625 50 25.25 

>  buy 10/25/01 100 12.625 50 25.25 

>  buy 09/1/01 100 12.625 50 25.25 

>  buy 1/23/01 100 12.625 50 25.25 
";
> 
> I would like to sort this by the date (ie the second field) in the
> above string. 
> 
> So it looks like this:
> 
> $a = 
> "buy 1/23/01 100 12.625 50 25.25 
";
>  buy 09/1/01 100 12.625 50 25.25 

>  buy 10/23/01 100 12.625 50 25.25 

>  buy 10/25/01 100 12.625 50 25.25 
;
> 
> What's the cleanest way to do this?

Roy,

You need to be *extremely* specific about how your input and output should look.  Your 
input, for
example, has a 
 followed by a newline.  That interpolates as two newlines between each record.  
Further, all
records after the first have a space before the word 'buy'.  Is this truly reflecting 
your data? 
Your output is also not valid Perl.  I'll show you what I came up with, but it's going 
to be
difficult to maintain if you're not familiar with map and sort.

##########################################
use strict;
use Data::Dumper;

my $data = "buy 1/23/01 100 12.625 50 25.25 

 buy 09/1/01 100 12.625 50 25.25 

 buy 10/23/01 100 12.625 50 25.25 

 buy 10/25/01 100 12.625 50 25.25 
";

my @data = split /

/, $data;

@data = map  { join ' ', ( $_->[0], ( join '/', @{$_->[1]} ), $_->[2] ) }
                sort { $a->[1][2] <=> $b->[1][2] || $a->[1][0] <=> $b->[1][0] || 
$a->[1][1] <=> $b->[1][1] }
                map  { [ $_->[0], [split ///, $_->[1]], $_->[2] ] }
                map  { [split( /s+/, trim( $_ ), 3) ] } @data;
print Dumper @data;

sub trim {
        my $data = shift;
        $data =~ s/^s+//;
        $data =~ s/s+$//;
        return $data;
}
##########################################

I was going to clean that up and document it, but then I realized that since I was 
unsure as to
whether or not my understanding of your input was accurate, I could be spending a lot 
of time
explaining something that doesn't fit what you need.  Regardless, here's a brief 
explanation:

I split the data on two newlines (since this is what you have).

The first map in the Schwartzian transform (read them bottom to top) splits the data 
on spaces
(after trimming out extraneous beginning and closing whitespace) and uses splits 
optional 3rd
parameter to limit the split to three scalars:

This:
    ' buy 10/25/01 100 12.625 50 25.25 '
Becomes:
    'buy', '10/25/01', '100 12.625 50 25.25'

The next map splits the second element (the date) on the forward slash and creates an 
array ref
for that element.

The sort sorts on the year, then the month, then the day.

The last map then puts the string back together.  Note that the beginning and ending 
whitespace is
lost.  If that's important, you'll need to modify this solution.

I realize that this is probably very confusing if you haven't used this before, so I 
offer my
apologies.  If you have show us your *exact* input data and the code that reads it, we 
can
probably offer an easier to follow solution.

Cheers,
Curtis "Ovid" Poe

=====
Senior Programmer
Onsite! Technology (http://www.onsitetech.com/)
"Ovid" on http://www.perlmonks.org/

__________________________________________________
Do You Yahoo!?
Make a great connection at Yahoo! Personals.
http://personals.yahoo.com

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to