如何在不使用临时数组的情况下访问最后一个Perl哈希键?

如何在不使用临时数组的情况下访问最后一个Perl哈希键?,perl,hash,Perl,Hash,如何访问散列中键的最后一个元素而不必创建临时数组 我知道散列是无序的。但是,也有一些应用程序(比如我的),在这些应用程序中,可以使用对散列键的简单sort调用对我的键进行排序。希望我已经解释了我为什么想要这个。我承认,barney/elmo示例是一个糟糕的选择,但它确实有其应用 考虑以下几点: my %hash = ( barney => 'dinosaur', elmo => 'monster' ); my @array = sort keys %hash; print $arra

如何访问散列中键的最后一个元素而不必创建临时数组

我知道散列是无序的。但是,也有一些应用程序(比如我的),在这些应用程序中,可以使用对散列键的简单
sort
调用对我的键进行排序。希望我已经解释了我为什么想要这个。我承认,barney/elmo示例是一个糟糕的选择,但它确实有其应用

考虑以下几点:

my %hash = ( barney => 'dinosaur', elmo => 'monster' );
my @array = sort keys %hash;
print $array[$#{$hash}];
#prints "elmo"
关于如何在不调用temp的情况下(在本例中为@array)执行此操作,您有什么想法吗

请注意,额外的参数是必要的,以防止语法与
print
的参数列表混淆

您还可以使用这个邪恶的伎俩将其强制到标量上下文中,并删除额外的参数:

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

散列是无序的,因此没有“最后一个元素”这样的东西。用于迭代散列的函数(
,和
每个
)都有顺序,但这不是您应该依赖的

从技术上讲,哈希具有迭代器使用的“哈希顺序”。散列顺序取决于散列算法,散列算法可以在不同版本的Perl之间更改(并且已经更改)。此外,从5.8.1版开始,Perl包含散列随机化功能,可以更改散列算法以防止某些类型的攻击

一般来说,如果您关心顺序,您应该使用数组来代替。

根据:

散列是数据的无序集合 按其索引的标量值 关联的字符串键


因为散列是无序的。所以,对不起。没有“last”元素。

哈希是无序元素。因此,可能是您的散列最后一个元素是elmo/

为了让其他人的观点更清楚,Perl中的散列键在您每次调用键、值或同一进程生命周期内的每一个键时都具有相同的顺序,假设散列未被修改。发件人:

钥匙显然是按随机顺序返回的。在未来的perl版本中,实际的随机顺序可能会发生更改,但可以保证其顺序与值或每个函数生成的顺序相同(假定哈希未被修改)。由于Perl 5.8.1,出于安全原因,即使在不同的Perl运行之间,顺序也是不同的(请参阅perlsec中的“算法复杂性攻击”)


一般来说,假设您想要按字母顺序排列的最后一个,它很简单:

use List::Util qw( maxstr );

print maxstr(keys %hash);
如果您不想使用模块(我看不出合理的理由,但有些人喜欢让它变得更难):

$h{'11c'}='C';
$h{'b'}='b';
$h{'e22'}='E';
$h{'aaaaa'}='AAAA';
用于(键%h){
如果$a<\$h{$},则$a=\$h{$}和$b=$};
}
打印“$b\n”;

但是要小心,因为显而易见的原因

,这就解释了为什么$#{$hash}首先返回-1。谢谢你的提示。
%hash
$hash
是完全不同的变量
$#{$hash}
返回-1,因为它自动激活
$hash
作为对匿名数组的引用。由于该数组是空的,(不存在的)最后一个元素的索引是-1。为了澄清friedo的答案:这将打印迭代器将返回的最后一个键的值(以哈希顺序)。它不会打印插入的最后一个键。另一个避免打印参数大括号的技巧是:打印+(键%hash)[-1];所以你实际上要做一个(排序{$a cmp$b}键%hash)[-1]?你的编辑没有提供太多的解释。当然,您可以对哈希键列表进行排序,但这里不显示。我可以想象在排序后想要最后一个键,但我想不出一个好的理由想要它,这就是你的代码试图做的。无论你做什么,或者你如何做,你总是会创建一个数组。这只是一个是否维护句柄的问题。@Zaid:Arrays保留插入顺序,hash不保留。排序与创建新的排序不是一回事。这并不完全正确。在这些情况下,如果不更改散列,散列键将以相同的顺序出现。请重新阅读我回答的第一句话。您编辑的。对于tie()d散列,这也不总是正确的。
use List::Util qw( maxstr );

print maxstr(keys %hash);
print( (sort keys %hash)[-1] );
$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";