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 Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

More SORT questions 1

Status
Not open for further replies.

tlogan

Programmer
Jun 26, 2001
33
US
Hello All -

I'm relatively new to Perl (I've been in mainframes for 15 years, though) and am having a lot of trouble understanding, hash, array and how to sort. I have installed a version of Selena Sols' Webstore (as well as Matt Kruse's CALENDAR (which I've modified to read a MySQL database) and Chris Hardie's DB_Browser) just so you know I have SOME idea of wwhat's going on. I would like to sort my newest items to the top. Currently, Items are retrieved in the order they are entered. I think I've found that the easiest and least intrusive place to do this is at the completion of the "Add Item" code and just sort the entire file after the "add." (The file is small enough that speed and size shouldn't be an issue.) Additionaly, I'd like to sort the first field ascending and the second descending. Can someone help me out here? Is there an easy way to sort this entire file?

Here is the current code that completes the "ADD" process:
Code:
##

open (NEW, "+>> $datafile");

print (NEW  "$in{'sku'}|$in{'category'}|$in{'price'}|$in{'name'}|$formatted_image|$formatted_description|$formatted_option_file\n");

close(NEW);

##


Thanks,
Tom
 
With the format of the file as you show above, I don't know how you would sort the newest items to the top. But as far as sorting on sku (1st field) ascending and category (2nd field) descending. That's not too much of a problem:
Code:
open (NEW, "$datafile");
@data = <NEW>;
close NEW;
@data = sort MySortRtn @data;
open (NEW, &quot;>$datafile&quot;);
print NEW @data;
close NEW;
Then you need your sort subroutine:
Code:
sub MySortRtn {
   my ($sku_a, $cat_a) = split(/\|/, $a, 2);
   my ($sku_b, $cat_b) = split(/\|/, $b, 2);
   return $sku_a cmp $sku_b or $cat_b cmp $cat_a;
} # MySortRtn
I think that will do what you want, but be sure to back up your data file before you try this!
Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
tsdragon -

Thanks, but perhaps I wasn't clear in what I'm trying to accomplish. I'd like to perform a two-level sort. Using the file layout from above, I'd like to get all of the categories ascending, then WITHIN category, SKU descending. After correcting for sorting category first (my bad, sorry), I've tried about every combination of &quot;AND&quot;, &quot;OR&quot;, &quot;cmp&quot;, &quot;<=>&quot; I could think of. I even tried creating a second sort routine and ran it through twice, once for cat and once for sku. It appears as though in all cases, I can only get it by CAT ascending or SKU desending. Can this be done? Here is some test data so you can see what I'd like to do:

BEFORE:
1|cd|15.00 ....
2|cd|15.00 ....
4|ts|10.00 ....
3|cd|18.00 ....
5|ts|12.00 ....

AFTER:
3|cd|18.00 ....
2|cd|15.00 ....
1|cd|15.00 ....
5|ts|12.00 ....
4|ts|10.00 ....

Thanks again...I've gotten further than I have before!
Tom
 
You should be able to just change the one line in the sort routine like this:
Code:
   return $cat_a cmp $cat_b or $sku_b cmp $sku_a;
Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
tsdragon -

Sorry, still not working. That was one of the combinations I tried earlier, but cut-and-pasted yours anyway, just in case I fat-fingered anything.

Here's what I end up with:

3|cd|18.00 ....
1|cd|15.00 ....
2|cd|15.00 ....
4|ts|10.00 ....
5|ts|12.00 ....

It appears as though the $cat is sorting correctly, with the $sku I want at the top, but then the rest of them are sorting by ascending $sku.

This is getting too weird. Any other ideas?

Thanks again,
Tom


 
You could try replacing the word or with the || symbol, but I'm not sure that would affect anything. Other than that I can't see anything about the sort routine that could be changed effectively. Maybe you should try printing out $cat_a, $cat_b, etc. in the sort routine to make sure they are being parsed correctly by the split. Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
tsdragon -

Having worked on IBM mainframes for 15 years, it always seems to come down to the things that shouldn't make a difference that always do!

OK, here's what I've got now:

You were right, the split wasn't working properly. I had to change the value of the limit from 2 to 3. Don't ask me why, but it works. I also had to change the &quot;or&quot; to &quot;||&quot;. Again, don't ask me why.

However, now it does not sort and print the last record. I start out with 5 records and end up with only 4! Those four are sorted properly though. Printing out the intermediate results (as you suggested...THANKS!) shows that the sort does not appear to be completing the final iteration on the record that should appear last evn though it read it properly earlier in the process.

Any suggestions?

Thanks a million!
Tom
 
I can see now why you had to change the limit to 3. When you specify a limit it puts the remainder of the string in the last item! Therefore you had to specify 3 to get two items and the remainder. As for changing 'or' to ||, the only difference between the two is that 'or' has a much lower precedence, which means it may have been doing &quot;a cmp (b or c) cmp d&quot; instead of &quot;(a cmp b) or (c cmp d)&quot; though it seems to me that with lower precedence it should be the other way around. You could put the parens in to make sure it's doing what it should. Both operators have the same &quot;short-circuit&quot; behavior though, so that wasn't the problem.

Now, as for the last record problem: I've never heard of that problem before. Have you tried printing the @data array before and after sorting? How are you reading and writing the file? It's hard for me to tell what might be happening without more info on the problem.

At least we're partway there. :) Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
tsdragon -

You are a GOD!!!!!!!! I bow to you're superior intellect!


Sort now works PERFECTLY. HAD to use &quot;||&quot; instead of &quot;or&quot;, even using parens with the &quot;or&quot;.

I've just pulled a HUGE Homer Simpson (&quot;DOH!&quot;)... Apparently, while cutting-and-pasting to create test data, the new-line character was chopped off of the last physical record. What was happening was that the file was sorting and writing out all of the data, but in the output, the record following the last physical record in the sort order was not printing on a new line, so it APPEARED as if there were only 4 records printing. I discovered this using your advice to print out the array before and after sorting. That showed that all of the data was being read and sorted. After that I had to look VERY CAREFULLY at the output file. (&quot;After you've eliminated the obvious, all that's left is the un-obvious&quot;, or something like that.) The problem was that that one record was very wide and I didn't catch that it was actually 2 records (and the fact that the &quot;missing&quot; record was supposed to sort to the bottom really confused things).

I guess I still have a LONG way to go!

Thanks for all your help.
Tom
 
I'm glad you caught that! Actually, believe it or not, after you printed the data before and after, that was one of the things I was going to mention to check for: a missing newline on the last record.

I'm still not exactly sure why one type of or worked and the other didn't, especially with parens to make things specific. Maybe someone can explain THAT little detail to both of us.

You haven't got THAT far to go - I still make wierd mistakes like that too. The or problem would have had me pulling my hair out.
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