[英]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.