www.webdeveloper.com
Results 1 to 10 of 10

Thread: sorting by field HELP!

  1. #1
    Join Date
    Jan 2006
    Posts
    301

    sorting by field HELP!

    I have been racking my brain trying to figure this out for 3 days and I can't get it. I hate asking for help or questions but my need for this to work is greater. :-)

    I have a perl script that edits a flat file that I want to add the functionality of sorting by field name by 123 or 321 or abc or cba. The url would look like this.
    ...com/admin.pl?order=FieldName&order_by=321

    You probably would need the whole Perl code let me know but this is the snippet I'm trying to use:

    $order = "ORDER BY ID ";
    if($FORM{order}){
    for (@show_fields){
    if($_ eq $FORM{order}){
    $order = "ORDER BY $FORM{order} ";
    $order.= $FORM{order_by} eq '321'? "DESC":"";
    last;
    }
    }
    }


    Any help is appreciated!

  2. #2
    Join Date
    Dec 2002
    Location
    Pleasanton, CA
    Posts
    2,132
    Your question does not make a lot of sense, which is probably why you're not sure what to do.
    I have a perl script that edits a flat file that I want to add the functionality of sorting by field name
    OK so far, but what does this mean?
    by 123 or 321 or abc or cba.
    You say you want to sort a 'flat file', but ORDER BY ID would indicate that you are using a database.

    Post a line or two of the flat file and explain what you are trying to order by.
    Are you trying to order the content of the flat file by a 'field name', or are you trying to order the content of the 'field name'?

    And you really should be using 'strict' and the CGI.pm module.

  3. #3
    Join Date
    Jan 2006
    Posts
    301
    Nedals, thanks for the reply back. My flat file is a database sorry that is pipe delimited. here is a sample.

    Color|Name|Sex|ID
    Red|Ted|M|1000000
    Blue|Larry|M|1000001
    Yellow|Sally|F|1000002

    I would be sorting by any field(Color, Name, Sex or ID) in the database from a link like this:

    Example 1
    admin.pl?order=Color&order_by=abc
    this would yeild the output of
    Blue, Red, Yellow

    Example 2
    admin.pl?order=Color&order_by=cba
    this would yeild the output of
    Yellow, Red, Blue.

    This would be the same with 123 or 321 with number fields like ID.

    I have attached the Sub Read part of the script to show you.
    Attached Files Attached Files
    Last edited by HDC; 01-28-2007 at 08:14 PM.

  4. #4
    Join Date
    Dec 2002
    Location
    Pleasanton, CA
    Posts
    2,132
    OK!
    I'm pretty sure you mean sort by a field in ASCENDING or DESCENDING order

    I would use
    admin.pl?order=0 - for ascending, default (abc,123)
    admin.pl?order=0&desc=1 - for descending (cba,321)

    The order value will be 0-color, 1-name, 2-sex, 3-id

    If you have a small file, say less that 50k records, I would read the whole thing into a hash where the hash key is the sort field. Now sort the keys in ascending or decending order and write the data into a temp file. rename the old file .bak. and rename the temp file.

    Might look something like this
    Code:
    my $order = $FORM{order}; ## better to use the CGI.pm module
    my $desc = $FORM{desc} || 0;
    
    #open file to read
    my %hash;
    while (<FIL>) {
      my @line = split(/|/);
      $hash{@line[$order]} = $_;
    }
    #close file
    
    my @hashkeys = keys %hash;
    if ($desc) { sort {$b cmp $a} @hashkeys; } else { sort @hashkeys; }
    
    #open temp file to write
    for (@hashkeys) {
      print TMP $hash{$_};
    }
    #close file

  5. #5
    Join Date
    Jan 2006
    Posts
    301
    Nedals do I need to append the code below into my Sub Read portion of the script. Also I'm not sure excatly what you mean by saving a back up of my database file and renaming it. When I do a sort it must pull from the "live" database for real time data. Not sure what that snippet actually does.

    Thanks

  6. #6
    Join Date
    Jan 2007
    Location
    Colorado Springs
    Posts
    24

    working snippet and more

    HDC,

    I suggest you put "use strict;" at the top of your script. It will catch more errors, require you to declare variables (fixing scope issues), etc. At the beginning of the script you attached, you declare an array data to be based on the sub order, but inside order you use data before it's been initialized! Unless it's initialized in code you didn't include, it could cause you trouble.

    You may want to try turning your @data array into an associative array. This is what I do when I am reading in such files. If you don't understand it, either try to figure it out or don't use it; I haven't tested it. Skip to below the code.

    my $data = {}; # a reference to an associative array
    my @keys = ();
    my $row = 0;

    #loop through lines in the file
    while (<FILE>) {
    chomp();
    if ($row == 0) {
    # legend row
    @keys = split("|", $_);
    } else {
    # data row
    my $row = {};
    my @values = split("|", $_);

    # loop through items between the pipes
    for (my $i = 0; $i < scalar(@values); $i++) {
    $row->{$keys[$i]} = $values[$i];
    }
    $data->{$values[0]} = $row;
    }
    }
    # now you have a hash
    # $data with keys being the first element of each row
    # and values being another hash
    # with keys being the legend on the first row.
    # NOW you should be able to use grep, map, & sort with
    # fewer "for" loops.

    Are you familiar with hashes (associative arrays) and the commands "grep" and "map"?
    If not, you will appreciate how smooth they make your script. It will also help in that you'll have fewer loops with if statements tucked inside - and fewer bugs. But you MUST understand how they work before you use them.

    First, grep. Grep will pull out exactly what you want from an array, based on the conditional inside brackets. This conditional can be more than one statement but must return a value; 0 means don't include it, more than 0 means include it.
    The following will return an array containing any elements from @show_fields that equal $FORM{order}.

    my @array = grep { $_ eq $FORM{order} } @show_fields;

    Next, map. Map will turn an array into a different array based on the return value from the subroutine within brackets.

    my @array2 = map { "ORDER BY $_" } @array;

    Done correctly, this will return an array of one element containing the string you want. Code follows, but I combined the grep & map. I did test this snippet alone and it worked.

    $order="ORDER BY ID ";
    if ($FORM{order}) {
    $order = (map { "ORDER BY $_" } grep { $_ eq $FORM{order} }
    @show_fields)[0];
    }

    If it doesn't work for you, I suggest you check the rest of your code.

    Good luck!
    Mary

  7. #7
    Join Date
    Dec 2002
    Location
    Pleasanton, CA
    Posts
    2,132
    Perhaps I should not have responded to this thread. I do not have the time to work with you on incorporating this code into your script. Hopefully someone else can be of help. (that's why i'm posting this)

    I don't know where this snippet of code will fit into your overall script. All it does is to take data that is read from a file and sorts it based on a specified field either in ascending or descending order. What you do with the resulting data is entirely up to you.
    ...I have a perl script that edits a flat file...
    How do you currently handle your edited data? You probably need to do something similar with the sorted data.

    NOTE: I don't even know if this snippet works. It's just an idea to give you a way of thinking.

  8. #8
    Join Date
    Jan 2006
    Posts
    301
    Thanks Nedals for your suggestions, and thanks Mary for the code and a little tutorial. I do appreciate it!

    However when inserting the code it did nothing. I don't get a cgi error nor does the script act any differently. I will continue to try different variations here.

    Thanks!

  9. #9
    Join Date
    Jan 2007
    Location
    Colorado Springs
    Posts
    24
    I think your bug is deeper in the code. To search for it, comment out most of your program but leave a little bit. Make sure that little bit works (using print statements), then uncomment some more code. Go on and on until you know everything works. It's tedious, but a great way to verify that the other parts of your code work. And it's not something that anyone but you can do- it's your program!

    Good luck!
    Mary

  10. #10
    Join Date
    Feb 2007
    Posts
    2

    Sort by computed field

    #!/usr/bin/perl
    use strict;
    use warnings;

    my @lines;

    print "The raw data:\n";
    while (<DATA>)
    {
    print;
    push @lines,[ (split /\|/)[0],$_]; # [0] grabs the whole line
    }
    print "=" x 20,"\n";

    # sort by color, ascending
    print "Sorted by color, ascending:\n";
    print map {$_ ->[1]}
    sort { $a->[0] cmp $b->[0]}
    @lines;
    print "=" x 20,"\n";

    # sort by color, descending
    print "Sorted by color, descending:\n";
    print map {$_ ->[1]}
    sort { $b->[0] cmp $a->[0]}
    @lines;
    print "=" x 20,"\n";

    # sort by name, ascending
    print "Sorted by name, ascending:\n";
    print map {$_ ->[1]}
    sort { $a->[1] cmp $b->[1]}
    @lines;
    print "=" x 20,"\n";

    # sort by name, descending
    print "Sorted by name, descending:\n";
    print map {$_ ->[1]}
    sort { $b->[1] cmp $a->[1]}
    @lines;
    print "=" x 20,"\n";

    __DATA__
    Red|Ted|M|1000000
    Blue|Larry|M|1000001
    Yellow|Sally|F|1000002

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles