Вы находитесь на странице: 1из 4

Sortinghashes

bykeyorbyvalue
Sortinghashes,whetherbykeyorbyvalue,alsostartswithalistofthekeysinthe
hash.Youcanthensortthekeysorvaluesofthehashusingsyntaxverysimilarto
thatyoualreadyknowforsortingarrays.

SortingASCIIbeticallybykeys
Considerthesimplestcase,wherewewanttosortthekeysofahashASCIIbetically.
Forexample,thehashmaycontaingenesequencesasvalues,andgenenamesas
keys,andyouwanttoprintoutthesequencesinfastaformat,sortedbygenename.
Yousimplygetalistofthekeys,andthensortthemusingthesamesyntaxaswhen
sortingarrays:
sort keys %hash

keys%hashreturnsalist,andsortsortsthatlist.
Justlikewitharrays,thesortingwon'tbepreservedunlessyoudosomethingwithit.
Witharrays,wetypicallyassignedthesortedarraytoavariablename.Youcanalso
dothatwithyoursortedlistofhashkeysjustassignittoanewarray.Butbecause
hashesareuntrinsicallyunordered,youcan't"sortthehash"andhaveitstaysorted
untilyoudowhateveryouwanttodotoit.Instead,youcansortthekeyswithina
foreachloop,anddowhatyouplantodotoeachkeyorvalueasyouloopacrossthe
sortedlistofkeys:
foreach my $key (sort keys %hash) {
#do something, like printing out the key and its value
print "$key $hash{$key}\n";
}

Sohereweusekeys%hashtogetalistofkeys,andsorttosortit.Wethenwork
throughthislist,oneelementatatime,assigningeachelementinturntothecontrol
variable$keyandworkingthroughthecommandsintheloop.Notethat,asalways,
yourhash,controlvariableetccanbecalledwhateveryoulikeIhavejustcalled
them$keyand%hashforsimplicity.

Exercise
Downloadthefileseqlengths23.txt.Writescripttoreadinthisdata(genenamesand
theirrespectivegenelengths),andprintoutthesameinfo,butsortedASCIIbetically
bygenename.[Solution]

Sortingnumerickeys

Sortingnumerickeys
Ifthekeysofyourhasharenumericvaluesratherthanstrings,againyouusethe
samesyntaxasyouhavealreadyusedonarraystosortthelistofkeys:
foreach my $key (sort {$a <=> $b} keys %hashes) {
# do something
}

keys%hashreturnsalistofkeys,andsort{$a<=>$b}tellsPerltosortthelist
numerically.Rememberthatthespaceshipoperator<=>sortsnumerically,and$a
and$baretheinbuiltvariablenamestowhichPerlassignstheelementsofyourlist
inturnwhileitisdoingapairwisecomparisonofthem.Sointhissort,$aand$bare
keysinthelist.

Exercise
Downloadthefileflyids23.txt.Itcontainsdataonhowmanyminutesfliesflewina
onehourperiod,wherethefirstcolumnistheflyindividual'sID,andthesecond
columnisthenumberofminutesitflew.PrintouttheflyIDsandtheirflighttimesfor
thosefliesthatflewmorethan10minutesinthehour.SorttheoutputbyflyID,
smallesttolargest.[Solution]

Sortingbynumerichashvalues
Ifyouwanttosortyourhashbyvaluesratherthanbykeys(e.g.forthedatafrom
theexerciseabove,youmaywanttosorttheoutputbyflyingtimeratherthanfly
ID),youmodifythesyntaxslightly.Now,ifyouaresortingahashbykeys,andthe
keysarenumeric,youwrite:
foreach my $key (sort { $a <=> $b } keys %hashes) { do something; }

Ifinsteadyouwanttosortbynumerichashvalues,you'dwrite:
foreach my $key (sort { $hash{$a} <=> $hash{$b} } keys %hashes) { do something; }

Inbothcases,$aand$brefertowhatevertwokeysfromthelistofkeysinthehash
arebeingcomparedatthatpointintime.Whenyoutype$hash{$a},thevalueof
thisvariablenameisthevalueassociatedwiththekey$ainthehash%hash,and
similarly$hash{$b}referstothevalueinthehashthathasthekey$b.Sincethe
twovariablesoneithersideofthe<=>arevalues,thatiswhatPerlwillsortyour
keysby.

Sortingbystringhashvalues
ThesyntaxmodificationworksthesamewayforsortingvaluesASCIIbetically,butit
requiresustousethefullersyntaxforASCIIbeticalsorting.Rememberfromsorting
arraysthatyoucansorttheelementsofanarrayASCIIbeticallyusingeitherofthese
twosyntaxes:

my @sortedarray = sort @array;


OR
my @sortedarray = sort { $a cmp $b } @array;

BecauseASCIIbeticalsortingisthedefaultsortinPerl,youcanleaveoutthebit{$a
cmp$b}whichtellsPerltosortASCIIbeticallyinascendingorder.Thesameistrue
whenyou'resortingthekeysofahashASCIIbeticallyyoucanuseeitherofthese
formats:
foreach my $key (sort keys %hash)

{ do something; }

OR
foreach my $key (sort { $a cmp $b } keys %hash)

{ do something; }

WhatifyouwanttosortahashASCIIbeticallybyvalues?Thisisthesyntax:
foreach my $key (sort { $hash{$a} cmp $hash{$b} } keys %hash)

{ do something; }

Againhere,thetwovariablesoneithersideofthecomparisonoperatorcmpare
valuesinthehash(thevaluesassociatedwithkeys$aand$b),sothatiswhatPerl
willsortyourhashon.

Syntaxsummary
Here'sanoverviewofthesyntaxyouusetosortbykeyorvalue,ASCIIbeticallyor
numerically.I'veputextraspacesin(whichPerldoesn'tcareabout)totryandshow
thecommonalitiesacrossallthedifferentcases.
key, ASCII:

foreach my $key (sort

keys %hash) { }

key, ASCII:

foreach my $key (sort {

$a cmp $b

} keys %hash) { }

key, numeric:

foreach my $key (sort {

$a <=> $b

} keys %hash) { }

value, ASCII:

foreach my $key (sort { $hash{$a} cmp $hash{$b} } keys %hash) { }

value, numeric:

foreach my $key (sort { $hash{$a} <=> $hash{$b} } keys %hash) { }

Theconsensussyntaxis
foreach my $key (sort { comparison type } keys %hash) {
do something;
}

where{comparisonstype}tellsPerlwhethertosort(a)onkeysorvalues,(b)
numericallyorASCIIbetically,and(c)inascendingordescendingorder(justreverse
theorderof$aand$btogetdescendingorder).

Exercises

Usingtheinputfileflyids23.txtthatyouusedforthepreviousexercise,writeascript
toproduceanoutputfilecontainingthesamedata,butreformattedsothatitis
sortedinascendingorderbyflighttime(thevaluesinthesecondcolumn).[Solution]
Usingtheinputfileseqlengths23.txtfromthefirstexerciseatthetopofthepage,
writeascriptthatprintsoutalistofgenes,fromlongesttoshortest.[Solution]
Downloadthefileseqs23.txt.Writeascripttoreadinthisdata,thenprintoutalist
ofgenes,sortedbygenename,togetherwiththelengthofthesequenceforeach
gene.[Solution]
Now,usingseqs23.txtagain,writeascriptthatprintsoutalistofgenes,sortedby
genelength.[Solution]

Вам также может понравиться