【问题标题】:How can I access the last Perl hash key without using a temporary array?如何在不使用临时数组的情况下访问最后一个 Perl 哈希键?
【发布时间】:2014-07-31 15:15:49
【问题描述】:

如何在不创建临时数组的情况下访问哈希中键的最后一个元素?

我知道哈希是无序的。但是,有一些应用程序(比如我的),可以使用对哈希键的简单sort 调用来订购我的键。希望我已经解释了为什么我想要这个。我承认,barney/elmo 的例子是一个糟糕的选择,但它确实有它的应用。

考虑以下几点:

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

关于如何在不调用临时(在这种情况下为@array)的情况下执行此操作的任何想法?

【问题讨论】:

  • 所以你实际上要做一个 (sort { $a cmp $b } keys %hash)[-1] ?
  • 您的编辑没有提供太多说明。当然,您可以对哈希键列表进行排序,但您不会在此处显示。我可以想象在排序后想要最后一个键,但我想不出一个很好的理由之前想要它,这就是你的代码似乎试图做的事情。
  • 无论你做什么,或者你怎么做,你总是会创建一个数组。这只是你是否保持对它的句柄的问题。

标签: perl hash


【解决方案1】:
print( (keys %hash)[-1]);

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

您还可以使用这个邪恶的技巧将其强制转换为标量上下文并取消额外的括号:

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

【讨论】:

  • 这解释了为什么 $#{$hash} 首先返回 -1。感谢您的提示。
  • %hash$hash 是完全不同的变量。 $#{$hash} 返回 -1 因为它自动激活 $hash 作为对匿名数组的引用。由于该数组为空,因此(不存在的)最后一个元素的索引为 -1。
  • 澄清friedo的回答:这将打印迭代器将返回的最后一个键的值(按哈希顺序)。它打印插入的最后一个键。
  • 另一个避免打印参数大括号的技巧:print +(keys %hash)[-1];
【解决方案2】:

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

use List::Util qw( maxstr );

print maxstr(keys %hash);

如果您不想使用模块(我认为没有正当理由,但有些人喜欢让它变得更难):

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

【讨论】:

    【解决方案3】:

    哈希是无序的,所以不存在“最后一个元素”这样的东西。遍历哈希的函数(keysvalueseach)有一个顺序,但这不是您应该依赖的任何东西。

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

    一般来说,如果您关心订单,则应该使用数组。

    【讨论】:

    • @Zaid:数组保留插入顺序,哈希不保留。排序与创建新排序不同。
    【解决方案4】:

    根据perldoc perldata

    哈希是无序的集合 由它们索引的标量值 关联的字符串键。

    因为哈希是无序的。非常抱歉。没有“最后一个”元素。

    【讨论】:

      【解决方案5】:

      为了让其他人的观点更清楚,假设哈希没有被修改,Perl 中的哈希键在您每次调用键、值或在同一进程的生命周期内的每一个时都将具有相同的顺序。来自perlfunc

      密钥以明显随机的顺序返回。实际的随机顺序在 perl 的未来版本中可能会发生变化,但它保证与值或每个函数产生的顺序相同(假设哈希没有被修改)。从 Perl 5.8.1 开始,出于安全原因,即使在 Perl 的不同运行之间,排序也是不同的(请参阅 perlsec 中的“算法复杂性攻击”)。

      【讨论】:

      • 这并不完全正确。如果您不更改哈希,哈希键只会在这些情况下以相同的顺序出现。
      • 重读我回复的第一句话。您编辑的那个。
      • 对于 tie() 的哈希值也并非总是如此。
      【解决方案6】:
      $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";
      

      ! 但要小心,原因很明显

      【讨论】:

        【解决方案7】:

        哈希是无序元素。所以你的哈希最后一个元素可能是 elmo /

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-29
          • 2015-06-26
          • 1970-01-01
          • 2013-03-08
          • 1970-01-01
          • 2019-06-25
          • 1970-01-01
          • 2016-12-12
          相关资源
          最近更新 更多