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

How do you sort array? 2

Status
Not open for further replies.

Guest_imported

New member
Jan 1, 1970
0
Hi All,

I have a Hash array with keys which are concatination of 3 values separated by a "~".
For ex: 1~AMS~D, 2~BDC~A, 10~ASTM~E etc..

I would like to see the output in the ascending order of the first value of the key.
i.e in the order 1~AMS~D,2~BDC~A,3~FTC~E,...10~ASTM~E

how ever when i sort the keys of the array, they display it in the following format:

10~ASTM~E, 1~AMS~D, 2~BDC~A......

How do i make it to start with 1,2,3...10,11,12.etc..?

Your help is greatly appreciated.

Thanks,
Madhu

 
You just need to split the key and do a numeric sort on the first part:

Code:
%h = (
	"2~afga~X" => "b",
	"12~ands~L" => "l",
	"1~ijdf~N" => "a",
	"3~FDSAF~V" => "c",
	"7~Udsd~U" => "g",
	"4~DSN~Z" => "d",
	"26~JDS~U" => "z",
	"16~NDFS~K" => "p"
);

foreach $k (sort { (my $a1) = split(/~/, $a, 1); (my $b1) = split(/~/, $b, 1); $a1 <=> $b1} keys %h) {
	print $h{$k};
}
print &quot;\n&quot;;
 
sackyhack ,

it works fine. thanks..

how ever if i need to sort the output based on BOTH the first and second values of the key, how do i do it?

for ex: %h = (
&quot;2~afga~X&quot; => &quot;b&quot;,
&quot;12~ands~L&quot; => &quot;l&quot;,
&quot;1~ijdf~N&quot; => &quot;a&quot;,
&quot;2~bcd~M&quot; => &quot;h&quot;,
&quot;1~dec~F&quot; => &quot;o&quot;,
&quot;2~zed~F&quot; => &quot;m&quot;,
&quot;1~abc~F&quot; => &quot;f&quot;,
&quot;3~FDSAF~V&quot; => &quot;c&quot;,
&quot;7~Udsd~U&quot; => &quot;g&quot;,
&quot;4~DSN~Z&quot; => &quot;d&quot;,
&quot;26~JDS~U&quot; => &quot;z&quot;,
&quot;16~NDFS~K&quot; => &quot;p&quot;
);


the output should be like:
&quot;1~abc~F&quot;
&quot;1~dec~F&quot;
&quot;1~ijdf~N&quot;
&quot;2~afga~X&quot;
&quot;2~bcd~M&quot;
&quot;2~zed~F&quot;
&quot;3~FDSAF~V&quot;
&quot;4~DSN~Z&quot;
&quot;12~ands~L&quot;
&quot;16~NDFS~K&quot;
&quot;26~JDS~U&quot;


Thanks for your help.
 
you'll just have to change the sorting controller. change the part of shadyhack's code immediately after the &quot;sort&quot; and inbetween the '{}' brackets to this:[tt]
{(my $a1, $a2) = split(/~/, $a); (my $b1, $b2) = split(/~/, $b); $a1 <=> $b1 || $a2 <=> $b2}[/tt]

you can then extend this all you want - add another $a#/$b# pair to the lists of variables in parentheses (assuming your data has that many '~' delimited fields), and then add a &quot; || $a3 <=> $b3&quot; to the end of it. &quot;If you think you're too small to make a difference, try spending a night in a closed tent with a mosquito.&quot;
 
You'd need to use cmp instead of <=> for the parts of the split that you want sorted alphabetically:
Code:
{(my $a1, $a2) = split(/~/, $a); (my $b1, $b2) = split(/~/, $b); $a1 <=> $b1 || $a2 cmp $b2}

That code is pretty cool. <=> and cmp evaluate to 0 when the values are equal, so the second comparison is only done when the first values are equal (short circuit evaluation). Just what was needed!
 
*d'oh*
shadyhack, thanks for noticing the 'cmp' ommission on my part. &quot;If you think you're too small to make a difference, try spending a night in a closed tent with a mosquito.&quot;
 
Thank you both for your help.
It works fine.

Thanks,
Madhu
 
Hi,
i have a similar problem. I tried the logic from above but it didn't work. Please help!.

I have an array
%h = (
&quot;2~afga~X~10/20/2000&quot; =>&quot;b&quot;,
&quot;12~ands~L~10/30/2000&quot;=>&quot;1&quot;,
&quot;1~ijdf~N~11/12/2000&quot;=>&quot;a&quot;,
&quot;1~dec~F~12/12/2000&quot;=>&quot;h&quot;,
&quot;1~abc~F~12/31/2000&quot;=>&quot;b&quot;,
&quot;2~bcd~F~12/31/2000&quot;=>&quot;c&quot;,
&quot;1~abc~A~12/30/2001&quot;=>&quot;d&quot;
);

The output should sort FIRST by the last value which is a date and next by the second value.
The output should be like:
2~afga~X~10/20/2000
12~ands~L~10/30/2000
1~ijdf~N~11/12/2000
1~dec~F~12/12/2000
1~abc~F~12/31/2000
2~bcd~F~12/31/2000
1~abc~A~12/30/2001

I tried something like :

foreach $test (sort {(my $a1,$a2,$a3, $a4) = split(/~/, $a); (my $b1,$b2,$b3,$b4
) = split(/~/, $b); $a4 <=> $b4 || $a2 cmp $b2 } keys %h) {
print $test;
print &quot;\n&quot;;
}
print &quot;\n&quot;;

It didn't work.

Any help is appreciated.

Thanks,



 
There's a couple of things wrong. First the split returns a list, so the list of variables should be in parens, the my should be outside the parens. Next, the operator you are using to compare the dates is only for numeric comparisons. However, since your dates are in mm/dd/yyyy format, that won't work. Lastly, you need to return the results of the cmp to the sort. Here's some code that should do it:
Code:
foreach $test (sort {
   my ($a1,$a2,$a3,$a4) = split(/~/, $a);
   my ($b1,$b2,$b3,$b4) = split(/~/, $b);
   my ($amm, $add, $ayy) = split(/\//, $a4);
   my ($bmm, $bdd, $byy) = split(/\//, $b4);
   return (
      $aay <=> $byy || 
      $amm <=> $bmm || 
      $add <=> $bdd || 
      $a2 cmp $b2);
   } keys %h) {
   print $test;
   print &quot;\n&quot;;
}
Tracy Dryden
tracy@bydisn.com

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top