Without seeing your test data or the way you're calling sort_func, it's hard to tell exactly what's going on. I tried it with this setup:
#!/usr/bin/perl -w
use strict ;
my @array = (
"row #1\t106\thello",
"row #2\t101\tgoodbye",
"row #3\t104\thi again!"
) ;
my $datafields = 3 ;
my $sort = 1 ;
my $sortby = "number" ;
print join ("\n", sort {&sort_func} @array) ;
This appears to work for both cases you mentioned. I don't think it's a precedence bug either. My guess is that one of your multitude of control variables is fouled up (this seems especially likely for $sortby -- doing a case-sensitive comparison with "magic" multi-character literal strings is dangerous, especially with no default case to catch mistakes.) With that said, why use a separate subroutine at all?
my $col = 1 ; # this is called "$sort" and "$item_no" in the original
my @sorted = sort {(split ("\t", $b)) [$col] <=> (split ("\t", $a)) [$
+col]} @array ;
Like I said, I don't have your test data so that might be totally useless to you, but it does work with the test data I used above (of course your original worked for me too). HTH! | [reply] [d/l] [select] |
Hi Devo, and welcome to PerlMonks.
I think that your specific question can be answered by reading more about sort and reverse. I suspect that your problem is not limited to the title of this node.(Descending Sort)
More generally, here are some obserations about your code.
- You try to avoid using the special variables '$a' and '$b', since they sometimes have special meaning, especially when dealing with sort; it's good to comment that out.
- Following a similar strategy, try to keep variables local to the scope, unless there's a good reason not to. For example,
your '$sortby' variable appears to have come from outside the function you've written. It is often better, though, to pass the variable as an argument to the function call. Like this:
my $adata = q(athings1 athings2);
my $bdata = q(bthings1 bthings2);
my $column = 0;
# ...
sort_func($column,$adata,$bdata);
sub sort_func
{
my ($sortby,$astring,$bstring) = @_;
# this function uses three arguments.
}
- Your function is returning the result of the 'cmp' and '<=>', in a string. The '$result' will then contain -1, 0, or 1. Is that what you wanted? It may be - but then, shouldn't you just split the strings and sort them, dispensing with the need of 'sort_func()'? Then, no more need for non-local variables, that I can see. To learn more about the comparison operators, read perlop.
- It appears that you are testing equivalence between two values, not actually attempting to sort. Did you mean to write something like this?
if ($sortby eq "string"){
my $result = sort { $b cmp $a } ($a_items[$item_no], $b_items[$item
+_no]);
}
# $result will contain the greater of the two values.
- Also, I'm not sure your split will do what you think it will as written. At least, I assume so because you've put a variable called '$datafields' in the 'LIMIT' argument of split. That means that if $datafields is 2, all the columns after the first column will be excluded from split. That's fine if there are only two columns (in which case, leave out the LIMIT), but what if you had three? So, I'd recommend renaming '$datafields' to '$exclude' or something more descriptive of what it does.
- However, on the assumption that you want to exclude all but a select number of columns of data from split (a good practice), then you might mean to remove that excluded data. I assume this because you seem to want to sometimes sort things numerically - which would never be applicable if the contents of the final element of the array is "111\t222\t333". In other words,
if you really meant to limit your split, then you need to jettison the irrelevant data.
my @a_items = split("\t", $astring,$limit);
#store the remainder
my $a_remainder = pop @a_items;
my @b_items = split("\t", $bstring,$limit);
#discard the remainder
pop @b_items;
I hope this isn't over-doing the answer (a lot of guessing at your intent) but, it appears that some of these observations might be relevant to why you aren't getting the result that you want.
mkmcconn
| [reply] [d/l] [select] |