Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Sorting Issues :(

by LostS (Friar)
on Jul 18, 2001 at 21:18 UTC ( #97774=perlquestion: print w/replies, xml ) Need Help??
LostS has asked for the wisdom of the Perl Monks concerning the following question:

OK Guys here is the issue... I have a flatfile DB type thing going on... it is a tab delimited file. The row I am trying to sort on is the 5 section. It is a time such as 9:00 AM or 2:00 PM... Now I need to list this in chronological (spelling) order... so it will look like this: 9:00 AM 10:00 AM 2:00 PM 9:00 PM This is my current sort code:
foreach $_ (sort { (split /\t/, $a)[4] cmp (split /\t/, $b)[4] } @data +base_in) { ..... }
This is fine however it lists it in numercial order only so 1:00 AM 2:00 PM 9:00 AM How can I make this so it displays it correctly?? Also I need to make it so that in case the user who filles out my form puts the time in as say 09:00 AM it will still list it in the correct position... Thanks :)

Replies are listed 'Best First'.
Re: Sorting Issues :(
by Masem (Monsignor) on Jul 18, 2001 at 21:28 UTC
    In this situation, a Schwatzian Transformation is going to be necessary, as you'll need to have some way to convert from "HH:MM AP" to, say, a 24hr time. Assuming that the times are all within the same day, you can use hand coded stuff, but there are always modules like Date::Manip that will convert the time string to a epoch time.

    But a simple starting point could be as follows:

    sub time_to_2400 { my $time = shift; my ( $hour, $min, $ap ) = ( $time =~ /^(\d{1,2}):(\d\d)\s([APM]{2}) +$/; $hour = 0 if $hour == 12; # return ( $hour * 100 + $minute + ( ( $ap eq 'AM' ) ? 0 : 1200 ) ); } my @sorted_list = map { $database_in[ $$_[0] ] } sort { $$a[1] <=> $$b[1] } map { [ $_, time_to_2400( (split /\t/, $database_in[ $_ ])[4] ) ] +} (0..@database_in-1);
    Update and to the second part of the question, whenever new data is added to the database, given that you're using a flatfile, you can either run this sort again to get it into the right place, or better, read the flat file line by line and write to a new version of it, inserting the new item into the right place based on the time field, then write out the remaining part of the original flat file to the new file, and then move the new file over the old file when done.

    Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain
      Sir, Your suggections works great... Now I have another issue dealing with this. Due to my users are complete morons... They may set the time as a HH:MM{AM/PM} without that space... What should I do to check for that space and if it isn't there add it?
        Due to my users are complete morons...

        Be careful with those stones: One might call someone who uses a sentence as poorly constructed as that a "moron", too.

        Your users are not morons. They're human. What's more, they're humans who don't really need to worry about whether there's a space between before the AM/PM. Why should they waste their human brain cycles dealing with something that the machine can handle just as well?

        Remember why we're programmers: "Machines should work. People should think." The whole point of the machine is to take the drudgery off the human. Taking a snippy attitude at your users benefits no one.

        Fortunately, Perl makes this sort of drudgery simple to handle, as you've already seen.

        Take the path to the light of helpfulness, not to the darkness of insulting your customers.

        Throw down the gun and tiara and come out of the float!

        Try this (in the regex...):
        $time =~ /^(\d{1,2}):(\d\d)\s?([APM]{2})$/ #----------------------------^ Added this # And actually, now that I come to think of it, the # dealing with AM or PM problems may be better sorted using: $time =~ /^(\d{1,2}):(\d\d)\s?(AM|PM)$/

        Note that you ought to use this regex after the user submits the data and before you enter it, so that if a user gives something bogus, you catch it then, before the data goes in, as opposed to afterwards during the sort.

        Dr. Michael K. Neylon - || "You've left the lens cap of your mind on again, Pinky" - The Brain

        To be on the safe side it's probably best to allow whitespaces (or none) in some more places which would turn the regex into: $time =~ /^\s*(\d{1,2})\s*:\s*(\d\d)\s*([APM]{2})\s*$/
        The \s* matches zero or more whitespaces and as many as possible (greedy). So this allows for any of the following (_ equals whitespace):

        _12:00_AM__ 1_:_00_PM 2:20AM
        And then you could allow for leaving out of AM/PM and assuming a 24 hour clock .... but /me gets carried away ;)

        -- Hofmator

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://97774]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (3)
As of 2017-04-30 01:58 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (534 votes). Check out past polls.