Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks:
I have a text file like
2011#just#just@just.com#105 2017#home#home@home.com#101 2010#employ#emply@employ.com#109

I am trying to create a sorting program to sort by the values separeted by the "#".
I open the file here... foreach $rec (@DB){ chomp($rec); ($num,$name,$email,$xnumber)=split(/\#/,$rec);

Can I have the sorting code after this, or I do have to do it before?
What would be the right aproach?
Thank you!

Replies are listed 'Best First'.
Re: Sort Problem
by dragonchild (Archbishop) on Mar 30, 2004 at 16:03 UTC
    Think it through. What exactly are you sorting on? If you want to sort on the first value, then the second, then the third, and sort asciibetically, then just do a sort on @DB. However, if you want to sort
    • On the second value, then the fourth value, then the first, etc
    • Each value differently, like the first value numerically, the second asciibetically, etc
    then, you have to split each line up into its component parts. Something like the following will help:
    my @records = sort { $a->[0] <=> $b->[0] || $a->[1] cmp $b->[1] || $a->[2] cmp $b->[2] || $a->[3] <=> $b->[3] } map { [ split '#', $_ ] } map { chomp; $_ } @DB;

    You have to read that code from bottom to top.

    1. You have all the lines in @DB
    2. Take each line and perform a chomp on it. Since chomp() returns the character(s) removed (if any), you need to explicitly return $_
    3. Create an array reference containing the values in the record (using split(), just like you were)
    4. Sort those records based on the elements of the record. <=> is a numeric sort. cmp is an asciibetical sort.

    When it's all done, @records will be an array containing array references. If you need more explanation, please ask.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      I might have a problem because after I splited the values of the array, @DB
      foreach $rec (@DB){ chomp($rec); ($number,$name,$email,$xnumber)=split(/\#/,$rec);

      I am printing the value on the screen, can this sorting be done before?
        Your question indicates you didn't even read what I wrote, nor are you attempting to understand what sorting is in Perl and how it is achieved. Go back and read my reply, Learning Perl by Randal Schwartz, and figure out what it is you're trying to get the computer to do.

        I think the biggest issue you're having is you haven't laid out the steps you want the computer to do. You're trying to design by coding, which is a very poor method. Especially when you're not comfortable with the language or programming in general.

        ------
        We are the carpenters and bricklayers of the Information Age.

        Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Re: Sort Problem
by graff (Chancellor) on Mar 31, 2004 at 07:04 UTC
    If I understand your question, you want the lines contained in @DB to be printed in sorted order. You didn't say which field the sorting should be based on, but I'll assume you want it based on the initial field. Your examples only show 4-digit numbers in the first field, but I'll assume that you could have 3-digit and/or 5-digit numbers as well, and you want the sort to be numeric. I think the part of the foreach loop that you are not showing is the part where you want to print the lines in sorted order. The answer to your question is that you need to apply the sort before going into the loop -- this could do it (if all my assumptions are correct):
    foreach $rec ( sort { $a <=> $b } @DB ) { chomp $rec; ($num,$name,$email,$xnumber) = split /\#/, $rec; # print and do whatever else you want... }
    The sort block uses numeric comparison; it will do the right thing with the strings in your example, no matter how many digits are in the first field. If you want to sort based on some other field in each line, you'll need to build a hash with the hash key being the field you are sorting on, and the value being the other fields in each line. That means you need one loop over @DB to split each line and store it in the hash; then you need a second loop to print out the data in sorted order, and this second loop begins with something like:
    foreach my $key (sort keys %dbhash) { # print the data found in $dbhash{$key} }