Академический Документы
Профессиональный Документы
Культура Документы
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:
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:
keys %hash) { }
key, ASCII:
$a cmp $b
} keys %hash) { }
key, numeric:
$a <=> $b
} keys %hash) { }
value, ASCII:
value, numeric:
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]