簡體   English   中英

如何對包含大量數據的Perl哈希進行排序?

[英]How do I sort a Perl hash that has tons of data?

我在Perl中對哈希進行排序。 運行我的Perl腳本時遇到內存不足錯誤:

foreach $key (sort (keys(%hash))) {
   ....
}

如何對包含大量數據的哈希進行排序?

sort keys %hash是低效的大型%hash在於,存儲器明智的,其大致等同於:

my @keys = keys %hash;
@keys = sort @keys;

因為它必須在進行排序時將三個密鑰副本保留在內存中(一個在散列中,一個在鍵列表中,一個在創建的排序列表中)。 foreach對迭代器的內存優化不適用。

由於哈希是如此之大,最好的選擇是讓它完全沒有內存。 將其粘貼在BerkeleyDB文件中。 如果你想保持密鑰的順序,哈希不是最好的選擇,樹就是。 我建議使用Berkeley BTree文件。 樹將有效地保持您的數據像數組一樣排序,同時提供像哈希快速查找。

這是使用BerkeleyDB的一個例子。 DB_File更簡單,文檔更好,但沒有利用BerkeleyDB的現代功能。 因人而異。

use BerkeleyDB;

my $db  = tie my %hash, 'BerkeleyDB::Btree',
              -Filename => "your.db",
              -Compare  => sub { $_[1] cmp $_[0] },
              -Flags    => DB_CREATE;

-Compare說明了如何提供自己的排序功能。 綁定的界面將是緩慢的。 除非您需要它像哈希一樣,否則請使用對象接口。

Perl FAQ有一些例子可以對哈希進行排序。 看看我如何排序哈希? 這是對高效Perl排序的全新觀察

如果您的鍵是整數,數字或最小大小的字符串,您可以使用Sort :: Packed:

use Sort::Packed qw(sort_packed);

my $hash_size = keys %hash;
my $max_key_len = 4;  
my $packed_keys = '\0' x ($max_key_len * $hash_size);
my $ix = 0;
while (my ($key, $value) = each %hash) {
  my $key_len = length $k;
  $key_len <= $max_key_len or die "key $key is too big";
  substr($packed_keys, $ix, $key_len, $key);
  $ix += $max_key_len;
}

sort_packed("C$max_key_len", $packed_keys);

$ix = 0;
while ($ix < length $packed_keys) {
  my $key = substr($packed_keys, $ix, $max_key_len);
  $key =~ s/\0+$//;
  print "$key\n";
  $ix += $max_key_len;
}

不可否認,這段代碼非常難看,但它會將內存使用量降至最低。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM