Re: Sorting based on any column
by Anonymous Monk on May 19, 2015 at 10:36 UTC
|
Look at your sort criteria: { $b->[$col_2sort] <=> $a->[$col_2sort] }. $col_2sort is 2, but that array element does not exist. Change the sort criteria to { $b->[1] <=> $a->[1] } and it works.
You really should be using strict and warnings, using them will help clean up your code.
| [reply] [d/l] [select] |
Re: Sorting based on any column
by smknjoe (Beadle) on May 19, 2015 at 14:36 UTC
|
Can you please give a before/after data example of what you are trying to accomplish? Your question seems a little vague and your input data doesn't lend much help, as column #2 is (4,9) and looks to already be sorted correctly.
And yes - as previous poster indicated, "use strict;" and "use warnings;" should be in every Perl script. | [reply] |
|
|
column #2 is (4,9) and looks to already be sorted correctly
Off by one - index 2 is the third column, (5,10). Also the OP appears to want a reverse sort - at least I'm assuming that based on the $b being before $a and the OP saying the current code doesn't work.
| [reply] [d/l] [select] |
Re: Sorting based on any column
by perlomatic (Initiate) on May 19, 2015 at 21:58 UTC
|
>Trying to create a Subroutine to sort array based on any column numerically when my array is having both characters and numercis
I am not sure I completely understand the example...but this will sort alpha and numeric
#! /usr/local/bin/perl -w
use strict;
my $data = [qw| z x y 2 1 3 |];
print 'no sort:' , @$data ,"\n";
print 'sort: ' , (sort _sort_a_tron @$data) , "\n";
sub _sort_a_tron {
no warnings;
return ( $a <=> $b or $a cmp $b );
}
# output #
# no sort:zxy213
# sort: xyz123
| [reply] [d/l] |
|
|
This is basically one of the solutions I offered above, but with a number of caveats about the data.
| [reply] |
|
|
1 ab 2 3 cd 4 5 6 6
9 rc 4 5 ef 6 3 4 1
7 fa 5 2 tg 5 9 9 0
3 bg 3 9 jh 5 2 2 1
I want to create a subroutine which takes two argument as input, First argument is array and second argument is column number on which sorting has to be done.
Say for example sort_array is a subroutine and I pass OBJD array and column to sort as arguments.
something like sort_array(\@OBJD,2) and this should provide me below output
1 ab 2 3 cd 4 5 6 6
3 bg 3 9 jh 5 2 2 1
9 rc 4 5 ef 6 3 4 1
7 fa 5 2 tg 5 9 9 0
Or something like sort_array(\@OBJD,6) and this should provide me below output
3 bg 3 9 jh 5 2 2 1
9 rc 4 5 ef 6 3 4 1
1 ab 2 3 cd 4 5 6 6
7 fa 5 2 tg 5 9 9 0
Would like to do it using regular sorting method as well as using 'Schwartzian transform' just to learn it.
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
Re: Sorting based on any column
by Anonymous Monk on May 19, 2015 at 17:24 UTC
|
Seems to me that the ability to transparently use <=> (numeric) vs. cmp (string), as-appropriate, is a major part of the question . . . ? | [reply] |
|
|
Yes, it seems important, if I understand correctly this OP' quote: "my array is having both characters and numercis".
I can see two ways to go about it. Presumably, when using this function, the user knows what there will be in the column, so that the type of comparison could a parameter passed to the function. Assuming this is Boolean parameter stored in the $numeric variable, it could lead to something like this (untested):
@sorted_array= map { $_->[0] }
sort { $numeric ? $b->[1] <=> $a->[1] : $b->[1] cm
+p $a->[1]}
map { [ $_, (split " ", $_)[$col_2sort] } @unsorte
+d_array;
The other way might possibly look simpler (but is probably less clean and more error-prone):
@sorted_array= map { $_->[0] }
sort { $b->[1] <=> $a->[1] || $b->[1] cmp $a->[1]
+}
map { [ $_, (split " ", $_)[$col_2sort] } @unsorte
+d_array;
This is based on the idea that comparing two strings with <=> will yield 0, a false result, so that, if we have strings, the cmp comparison will be executed and return the correct comparison. But there are at least two downsides with this approach:
1. You need to silence out the Argument "foo" isn't numeric in numeric comparison (<=>) at ... warning with the appropriate pragma, and I usually hesitate quite a bit before deciding to silence out any warning (except perhaps, but only very very rarely, the initialized and the deep recursion warnings when I really know for sure it is OK);
2. There are several edge cases where it might break, especially if you have one numeric argument and one non-numeric argument:
$ perl -e 'print 3 <=> "b"'
1
~
$ perl -e 'print 3 cmp "b"'
-1
So this could work out for a one-off sort if you know your data very well, but this is really not very robust production code.
Update: Corrected two stupid typos in my code, thanks to AnomalousMonk for proofreading.
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
Re: Sorting based on any column
by Anonymous Monk on May 19, 2015 at 19:52 UTC
|
| [reply] |
|
|
| [reply] |
|
|
Ack, apologies, I spent too much time looking at the code and not enough reading the question. (In my defense, the OP's sample data isn't really representative then :-) )
| [reply] [d/l] |