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

Sorting rows per column - question on FAQ219-6545

Status
Not open for further replies.

kamielslets

Technical User
May 28, 2009
3
BE
Hello,
I'm looking for a variant of the solution in faq219-6545 "How do i sort columns/fields of mixed data?".

I my specific case i only need to sort one (of multiple) columns and take in the column number as a command line argument, such that i can choose which one to sort. Now, most
columns have plain numerical values (<=> operator can be used), but others have numerical values including a physical unit. Example: 6.2u or 500K or 3n. Is there a way to first interprete these units, convert them to something Perl understands and then start sorting them taking these orders of magnitude into consideration?

Thanks a lot!
 
You can probably remove all non-didgits before sorting:

$string =~ tr/0-9//d;

But if the unit of measure symbols are important to determine the type of sorting to perfotm it might be a little more complicated than just nuking the non-digits from the strings.


------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Also to be noted that, when perl interprets a string like 500K as a number, it will return the number 500: the same holds for anything that starts with something that can be interpreted as a number (even in scientific format or in hex). However a warning is issued if warnings are on.
So it is even not necessary to strip the non digits (and, Kevin, this would strip also the decimal point, the minus sign and other symbols used in numbers....)
But if, as noted by Kevin, the unit indicates a transformation to be done on the number before using it, then it's a different matter.

Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
Write a subroutine to convert the coded values into numbers. Then just
Perl:
sort {convertToNum($a) <=> convertToNum($b)} @stuff;

sub convertToNum {
   # Your conversion code here
   return $num;
}

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Thanks everyone. I indeed found that using the script as it is now, it sees 500K as just 500, and sorts all numbers with a similar postfix together. The same for micron, milli or whatever. It's already something...
But no clues for converting 500K to 500e3 ?
 
You could try something like this:
Code:
my %units = (	'M' => 10**6,
				'K'	=> 10**3,
				'H'	=> 10**2,
				'D' => 10**1,
				'none' => 1,
				'd' => 10**-1,
				'c' => 10**-2,
				'm' => 10**-3,
				'u' => 10**-6,
				'p' => 10**-9	);
				
my @input = qw/5 100m 100p 10H 90M 40u 10u 1/;
my @sorted = 	map {$_->[0]} 
				sort {	$units{$a->[2]} <=> $units{$b->[2]} ||
						$a->[1] <=> $b->[1] ||
						$a->[0] cmp $b->[0]	}
				map {m/\s*(\d+)([a-z]+)?/i; [$_, $1, ($2 || 'none')]} @input;
 
Thanks. I found this also to work:

my $n = 1;
my $unit = 'f|p|n|u|m|K|M|G';
my %phys_unit = (
'f' => 1e-15,
'p' => 1e-12,
'n' => 1e-09,
'u' => 1e-06,
'm' => 1e-03,
'K' => 1e+03,
'M' => 1e+06,
'G' => 1e+09
);

my @sorted =
map{ $_->[0]; }
sort{ $b->[$n+2] <=> $a->[$n+2] }
map{ @t = split(/\|/,$_);
@t_stripped = split(/\s+|($unit)/,$t[$n+1]);
if($t_stripped[-1] =~ /$unit/) {
$multiplier = $phys_unit{$t_stripped[-1]};
pop @t_stripped;
$t[$n+1] = join('',@t_stripped)*$multiplier;
};
[$_,$t[0],$t[1],$t[2],$t[3],$t[4],$t[5]];
} @file;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top