【问题标题】:Replicable iteration over a hash in perlperl中哈希的可复制迭代
【发布时间】:2016-03-28 15:31:12
【问题描述】:

众所周知,如何在 perl 中迭代哈希(参见,例如,What's the safest way to iterate through the keys of a Perl hash?)。但是,键和值的顺序是不确定的,实际上对于 perl 脚本的每次运行都是不同的。

有没有办法确保在相同的输入数据上每次运行相同的 perl 脚本都会产生相同的迭代顺序?我只关心这种意义上的可复制性——顺序不需要人类可以预测。

编辑:我根据迭代提出了这个问题,但也许不是散列的迭代,而是散列构建过程是不确定的。我可以设置一些初始化来以确定性和可复制的方式构建哈希吗?

【问题讨论】:

  • the order needs not to be predictable by a human being 插入哈希的键的顺序如何?
  • @Сухой27:没问题,这个订单和任何固定订单一样好。

标签: perl hash iteration replicate


【解决方案1】:

sort他们第一:

foreach my $key (  sort keys %hash ) { 

}

注意:默认排序是字母顺序,而不是数字。但是sort 将采用一个自定义函数,允许您按几乎任何您想命名的顺序进行排序。

或者,在数组中捕获排序并使用 that 来提取输出顺序。

my %content_for;
my @ordered_id; 

while ( <$input_filehandle> ) { 
    my ( $id, $content ) = split; 
    push ( @ordered_id, $id ); 
    $content_for{$id} = $content; 
}

print join ( "\n", @content_for{@ordered_id} ),"\n"

;

或者像Hash::OrderedTie::IxHash 这样的有序哈希机制。

我根据迭代提出了这个问题,但也许不是哈希上的迭代,而是哈希构建过程是不确定的。我可以设置一些初始化来以确定性和可复制的方式构建哈希吗?

没有。哈希不是那样工作的。请参阅 - perlsec 了解原因。它在新版本的 perl 中 more 是随机的,但它始终是一个无序的数据结构。

您也许可以乱用(如文章中所述)PERL_HASH_SEEDPERL_PERTURB_KEYS,但这绝对不是一个好习惯。

PERL_HASH_SEED=0 ./somescript.pl 

但您应该记住,仍然不能保证哈希排序 - 键的顺序可能仍然会改变。不过,它会比以前更加一致。这绝对不是在生产中使用的好东西,或者除了调试之外的任何依赖。

请注意:哈希种子是敏感信息。哈希是随机的,以防止针对 Perl 代码的本地和远程攻击。通过手动设置种子,这种保护可能会部分或完全丧失。

【讨论】:

  • :) 你只是打败了我几秒钟 :) sort 可能是实现这一目标的唯一方法。
  • 这是一个简单的答案,但还有其他的——比如使用Hash::Ordered ...基本上是在sort中构建的。
  • 这是一个很好的答案,但真的没有其他选择吗,比如设置一些初始化以使哈希可重现?
  • 没有。哈希是一组无序的键值对。这是因为它在内存中的排列方式(用于有效的随机访问)。如果你愿意,你可以使用不是散列的东西,但是你不能神奇地让一个无序的数据结构重新排序。
  • Tie::Hash::Indexed 提供与 Tie::IxHash 相同的功能,但速度明显更快。
猜你喜欢
  • 2023-04-07
  • 2017-09-04
  • 2014-10-27
  • 1970-01-01
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多