2009-07-10 8 views
4

一時的な配列を作成することなく、ハッシュ内のキーの最後の要素にアクセスするにはどうすればよいですか?一時的な配列を使用せずに最後のPerlハッシュキーにアクセスするにはどうすればよいですか?

私はハッシュが順序付けられていないことを知っています。しかし、単純なsortハッシュキーの呼び出しを使用して私のキーを注文できるアプリケーション(私のような)があります。なぜ私はこれが欲しいのか説明してくれることを願ってbarney/elmoの例は悪い選択ですが、私は認めますが、そのアプリケーションはあります。

は、次のことを考えてみましょう:

my %hash = (barney => 'dinosaur', elmo => 'monster'); 
my @array = sort keys %hash; 
print $array[$#{$hash}]; 
#prints "elmo" 

TEMP(この場合は@array)に呼び出さずにこれを行う方法上の任意のアイデア?

+0

実際に(sort {$ a cmp $ b} keys%hash)[ - 1]を実行しますか? – mkb

+0

@Matt:そうです。 – Zaid

+2

あなたの編集はあまり明確ではありません。もちろん、ハッシュキーのリストをソートすることはできますが、ここには表示されません。ソート後に最後のキーが欲しいと思うかもしれませんが、前に欲しいという正当な理由は考えられません。これはあなたのコードがしようとしているようです。 –

答えて

11
print((keys %hash)[-1]); 

余分な括弧がprintさんのparamリストと構文の混乱を防ぐために必要であることに注意してください。

あなたはまた、スカラーコンテキストにそれを強制し、余分な括弧を廃止するために、この邪悪なトリックを使用することができます

print ~~(keys %hash)[-1]; 
+0

これは、なぜ$#{$ hash}が最初に-1を返すのかを説明します。先端に感謝します。 – Zaid

+1

'%hash'と' $ hash'は全く異なる変数です。 '$#{$ hash} 'は無名配列への参照として' $ hash'を自動化するので-1を返します。その配列は空であるため、(存在しない)最後の要素のインデックスは-1です。 –

+0

friedoの答えを明確にするために、これはイテレータが返す最後のキーの値を(ハッシュ順で)出力します。挿入された最後のキーを印刷しません。 –

2

ハッシュは順不同ですので、のようなものはありません「最後の要素は。」ハッシュを反復する関数(keysvalues、およびeach)には順序がありますが、それに依存する必要はありません。

技術的に言えば、ハッシュには、イテレータが使用する「ハッシュオーダー」があります。ハッシュ順序はハッシュアルゴリズムに依存します。ハッシュアルゴリズムは異なるバージョンのPerlを変更することができます。さらに、バージョン5.8.1以降、Perlには、特定の種類の攻撃を防止するためにハッシングアルゴリズムを変更できるハッシュランダム化機能が含まれています。

通常、ご注文を気にする場合は、代わりに配列を使用する必要があります。 perldoc perldataによると

+0

@Michael:一般的ですが、必ずしもそうではありません... – Zaid

+1

@Zaid:配列は挿入順を保持しますが、ハッシュは保持しません。並べ替えは、新しい並べ替えを作成するのと同じではありません。 –

1

ハッシュはその 関連付けられた文字列のキーによってインデックスさ スカラー値の順不同の集合です。

ハッシュは順不同です。だから、申し訳ありません。 「最後の」要素はありません。

-1

ハッシュは順序付けられていない要素です。最後の要素はelmo/

1

です。他の誰かのポイントをもっと明確にするために、同じプロセスの存続期間内にキー、値、またはそれぞれを呼び出すたびに、Perlのハッシュのキーは同じ順番になります。ハッシュは変更されていません。からperlfunc

明らかにランダムな順序でキーが返されます。実際の乱数の順序は、将来のバージョンのperlでは変更される可能性がありますが、ハッシュ値が変更されていないと仮定すると、値または各関数が生成する順序と同じ順序であることが保証されます。 Perl 5.8.1以降、セキュリティ上の理由からPerlの実行が異なる場合でも、順序は異なります(perlsecの「アルゴリズムの複雑さの攻撃」を参照)。

+0

これは完全に真実ではありません。ハッシュを変更しないと、ハッシュキーは同じ順序でのみ出力されます。 –

+2

私の返答の最初の文を読んでください。あなたが編集したもの – mkb

+0

これは、tie()のハッシュでは必ずしも真ではありません。 –

4

一般的に、あなたが最後にしたいと仮定すると、アルファベット順にソート、それは簡単です:

use List::Util qw(maxstr); 

print maxstr(keys %hash); 

あなたは私がのために正当な理由が表示されていないいる(モジュールを使用することを希望されないが、人々が存在する場合)それは難しくしたい人:

print((sort keys %hash)[-1]); 
0
$h{'11c'} = 'C'; 
$h{'b'} = 'B'; 
$h{'e22'} = 'E'; 
$h{'aaaaa'} = 'AAAA'; 

for (keys %h){ 
     $a = \$h{$_} and $b = $_ if $a < \$h{$_}; 
} 

print "$b\n"; 

! 明白な原因のために注意してください

関連する問題