Another sort question.

M

Mal

Hi,
I've got some data that looks someting like this:


Disabled blah,blah,blah 18:00
Disabled blah,blah,blah 19:30
Enabled blah,blah,blah 1:30
Enabled blah,blah,blah 3:50
Enabled blah,blah,blah 23:30
Enabled blah,blah,blah 18:30
Enabled blah,blah,blah 20:50
Enabled blah,blah,blah 23:40


and I'm sorting it using:

sort {
$aEnabledField=substr($a,0,20);
$bEnabledField=substr($b,0,20);
($aHourField,$aMinField)=split /:/,substr($a,38,20);
($bHourField,$bMinField)=split /:/,substr($b,38,20);

$aEnabledField cmp $bEnabledField
||
$aHourField <=> $bHourField
||
$aMinField <=> $bMinField
}

which works in as much it sorts first by the Enabled/Disabled field,
and then by time. However I want to change it so that the time fields
after 17:00 are sorted first, and times before 17:00 sort last. So the
above data would come out like:


Enabled blah,blah,blah 18:30
Enabled blah,blah,blah 20:50
Enabled blah,blah,blah 23:30
Enabled blah,blah,blah 23:40
Enabled blah,blah,blah 1:30
Enabled blah,blah,blah 3:50
Disabled blah,blah,blah 18:00
Disabled blah,blah,blah 19:30


TIA for any help.

M:
 
A

Anno Siegel

Mal said:
Hi,
I've got some data that looks someting like this:


Disabled blah,blah,blah 18:00
Disabled blah,blah,blah 19:30
Enabled blah,blah,blah 1:30
Enabled blah,blah,blah 3:50
Enabled blah,blah,blah 23:30
Enabled blah,blah,blah 18:30
Enabled blah,blah,blah 20:50
Enabled blah,blah,blah 23:40


and I'm sorting it using:

sort {
$aEnabledField=substr($a,0,20);
$bEnabledField=substr($b,0,20);
($aHourField,$aMinField)=split /:/,substr($a,38,20);
($bHourField,$bMinField)=split /:/,substr($b,38,20);

$aEnabledField cmp $bEnabledField
||
$aHourField <=> $bHourField
||
$aMinField <=> $bMinField
}

which works in as much it sorts first by the Enabled/Disabled field,
^^^^^
Well, it kind of works. Not under strict, though, and it produces
a number of rather severe warnings ("substr outside of string..."),
which shows that the program doesn't understand the data correctly.
and then by time. However I want to change it so that the time fields

[snip]

Please first fix the program so that it runs cleanly under strict and
warnings, so we have a solid base to build on. I'm pretty sure what
you want can be done by simple modifications of your code, so the effort
won't be lost. At the moment, it is hard to tell what part of your
program's behavior is intended and what is buggy.

Anno
 
J

James Willmore

On 3 Dec 2003 22:38:13 GMT
Mal <[email protected]> wrote in comp.lang.perl.misc:
Please first fix the program so that it runs cleanly under strict
and warnings, so we have a solid base to build on. I'm pretty sure
what you want can be done by simple modifications of your code, so
the effort won't be lost. At the moment, it is hard to tell what
part of your program's behavior is intended and what is buggy.

Might I also add ...
perldoc -f sprinf
and
Date::Manip

I say this because the issue with your times is the format. If you
reformat the times into something standard, then you'll be able to
compare the times better :)

I'll leave it up to you (the OP) to find out which you prefer :)

HTH

--
Jim

Copyright notice: all code written by the author in this post is
released under the GPL. http://www.gnu.org/licenses/gpl.txt
for more information.

a fortune quote ...
Brain, n.: The apparatus with which we think that we think. --
Ambrose Bierce, "The Devil's Dictionary"
 
M

Mal

^^^^^
Well, it kind of works. Not under strict, though, and it produces
a number of rather severe warnings ("substr outside of string..."),
which shows that the program doesn't understand the data correctly.
and then by time. However I want to change it so that the time fields

[snip]

Please first fix the program so that it runs cleanly under strict and
warnings, so we have a solid base to build on. I'm pretty sure what
you want can be done by simple modifications of your code, so the effort
won't be lost. At the moment, it is hard to tell what part of your
program's behavior is intended and what is buggy.

Anno

When I said "the data looks something like this" it was only a very
rough idea, and in actual fact the string lengths & positions were not
nearly correct. Anyway here's a "cleaned up" version complete with a
bit at the start which will create some test data of the correct
length. Note that in real life this data is coming at me from an
application over which I have no control, the output is supposed to be
human readable and the positions of some of the fields may vary:

TIA for any more feedback.


use strict;
#
# Create some test data
#
open(testout,">test.dat");
print testout "Enabled blah,blah,blah 18:30\n";
print testout "Enabled blah,blah,blah 23:30\n";
print testout "Disabled blah,blah,blah 18:00\n";
print testout "Enabled blah,blah,blah 3:50\n";
print testout "Enabled blah,blah,blah 20:50\n";
print testout "Disabled blah,blah,blah 19:30\n";
print testout "Enabled blah,blah,blah 23:40\n";
print testout "Enabled blah,blah,blah 1:30\n";
close(testout);

open(test,"test.dat");
chomp (my @results=<test>);
foreach (sort {
my $aEnabledField=substr($a,0,20);
my $bEnabledField=substr($b,0,20);
(my $aHourField,my $aMinField)=split
/:/,substr($a,38,20);
(my $bHourField,my $bMinField)=split
/:/,substr($b,38,20);
$aEnabledField cmp $bEnabledField
||
$aHourField <=> $bHourField
||
$aMinField <=> $bMinField
} @results) {
print "$_\n";
}
 
A

A. Sinan Unur

(e-mail address removed) (Mal) wrote in @posting.google.com:
....

When I said "the data looks something like this" it was only a very
rough idea, and in actual fact the string lengths & positions were not
nearly correct. Anyway here's a "cleaned up" version complete with a
bit at the start which will create some test data of the correct
length.

Find out about the DATA file handle and __DATA__ section.
Note that in real life this data is coming at me from an
application over which I have no control,

Does the application change its output format at certain intervals?
the positions of some of the fields may vary:

In that case, techniques based on using the exact position of each field
are useless.
use strict;
#
# Create some test data
#
open(testout,">test.dat");

Always check if open succeeded. Also, turn on warnings:

use warnings;

Unquoted string "testout" may clash with future reserved word at C:\Home
\bzzt.pl line 9.

Unquoted string "test" may clash with future reserved word at C:\Home
\bzzt.pl line 20.

Use all caps for file handles: TESTOUT.

I really have nothing else to say about the rest of the code you posted
because I have a mental block against huge indents, line wraps, annoyingly
long variable names.

I put together something below. It probably is not the neatest way to do
it.

use strict;
use warnings;

my @data = <DATA>;
my @sorted = sort my_compare @data;
print @sorted;

sub my_compare {
my @aa;
my @bb;

if($a =~ /^(\w+)\s+.+\s+(\d{1,2}):(\d\d)$/) {
push @aa, $1, $2, $3;
}
if($b =~ /^(\w+)\s+.+\s+(\d{1,2}):(\d\d)$/) {
push @bb, $1, $2, $3;
}

return 1 unless(@aa);
return -1 unless(@bb);

return -1 if $aa[0] eq "Enabled" and $bb[0] eq "Disabled";
return 1 if $aa[0] eq "Disabled" and $bb[0] eq "Enabled";

if($aa[0] eq $bb[0]) {
return 1 if $aa[1] < 17 and $bb[1] > 17;
return -1 if $aa[1] > 17 and $bb[1] < 17;
return $aa[2] <=> $bb[2] if $aa[1] == $bb[1];
return $aa[1] <=> $bb[1];
}
}
__DATA__
Enabled blah,blah,blah 18:30
Enabled blah,blah,blah 23:30
Disabled blah,blah,blah 18:00
Enabled blah,blah,blah 3:50
Enabled blah,blah,blah 20:50
Disabled blah,blah,blah 19:30
Enabled blah,blah,blah 23:40
Enabled blah,blah,blah 1:30

C:\Home> bzzt.pl
Enabled blah,blah,blah 18:30
Enabled blah,blah,blah 20:50
Enabled blah,blah,blah 23:30
Enabled blah,blah,blah 23:40
Enabled blah,blah,blah 1:30
Enabled blah,blah,blah 3:50
Disabled blah,blah,blah 18:00
Disabled blah,blah,blah 19:30
 
M

Mal

I figured out that replacing

$aHourField <=> $bHourField
with
(($aHourField+17) %24) <=> (($bHourField+17) %24)

does what I need.
 
A

A. Sinan Unur

(e-mail address removed) (Mal) wrote in @posting.google.com:
I figured out that replacing

$aHourField <=> $bHourField with
(($aHourField+17) %24) <=> (($bHourField+17) %24)

does what I need.

Could you explain that please?

suppose

$aHourField = 7
$bHourField = 18

then

$aHourField + 17 = 24
$bHourField + 17 = 35

and

24 % 24 = 0
35 % 24 = 11

How did that change the comparison at all?
 
A

Anno Siegel

A. Sinan Unur said:
(e-mail address removed) (Mal) wrote in @posting.google.com:


Could you explain that please?

With a 24-hour clock it shifts the start of day from midnight to 7 am.

Anno
 
A

A. Sinan Unur

(e-mail address removed)-berlin.de (Anno Siegel) wrote in @mamenchi.zrz.TU-Berlin.DE:
With a 24-hour clock it shifts the start of day from midnight to 7 am.

Anno,

Thank you, I understand that. However, the OP's request was:

Now:

# mmm.pl
use strict;
use warnings;

my @n = (0 .. 23);

print (map { "$_," } sort { (($a + 17) % 24) <=> (($b + 17) % 24) } @n);
print "\n";

__END__

C:\Home> mmm.pl
7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,0,1,2,3,4,5,6,

It seems to me like the OP ought to be adding 7 instead of 17. After
changing the the line above to:

print (map { "$_," } sort { (($a + 17) % 24) <=> (($b + 17) % 24) } @n);

C:\Home\asu1> mmm.pl
17,18,19,20,21,22,23,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,143
Messages
2,570,822
Members
47,368
Latest member
michaelsmithh

Latest Threads

Top