r - 我可以在 R 中使用列表作为哈希吗?如果是这样,为什么这么慢?

标签 r perl hash

在使用 R 之前,我使用了相当多的 Perl。在 Perl 中,我经常使用散列,并且在 Perl 中通常认为散列的查找速度很快。

例如,以下代码将使用最多 10000 个键/值对填充哈希,其中键是随机字母,值是随机整数。然后,它在该哈希中进行 10000 次随机查找。

#!/usr/bin/perl -w
use strict;

my @letters = ('a'..'z');

print @letters . "\n";
my %testHash;

for(my $i = 0; $i < 10000; $i++) {
    my $r1 = int(rand(26));
    my $r2 = int(rand(26));
    my $r3 = int(rand(26));
    my $key = $letters[$r1] . $letters[$r2] . $letters[$r3];
    my $value = int(rand(1000));
    $testHash{$key} = $value;
}

my @keyArray = keys(%testHash);
my $keyLen = scalar @keyArray;

for(my $j = 0; $j < 10000; $j++) {
    my $key = $keyArray[int(rand($keyLen))];
    my $lookupValue = $testHash{$key};
    print "key " .  $key . " Lookup $lookupValue \n";
}

现在越来越多,我想在 R 中有一个类似哈希的数据结构。以下是等效的 R 代码:
testHash <- list()

for(i in 1:10000) {
  key.tmp = paste(letters[floor(26*runif(3))], sep="")
  key <- capture.output(cat(key.tmp, sep=""))
  value <- floor(1000*runif(1))
  testHash[[key]] <- value
}

keyArray <- attributes(testHash)$names
keyLen = length(keyArray);

for(j in 1:10000) {
  key <- keyArray[floor(keyLen*runif(1))]
  lookupValue = testHash[[key]]
  print(paste("key", key, "Lookup", lookupValue))
}

代码似乎在做等效的事情。然而,Perl 的要快得多:
>time ./perlHashTest.pl
real    0m4.346s
user    **0m0.110s**
sys 0m0.100s

与R相比:
time R CMD BATCH RHashTest.R

real    0m8.210s
user    **0m7.630s**
sys 0m0.200s

什么解释了这种差异? R 列表中的查找不是很好吗?

增加到 100,000 个列表长度和 100,000 次查找只会夸大差异? R 中的散列数据结构是否有比 native list() 更好的替代方案?

最佳答案

根本原因是带有命名元素的 R 列表没有经过哈希处理。哈希查找是 O(1),因为在插入期间使用哈希函数将键转换为整数,然后将值放入空间 hash(key) % num_spots数组 num_spots long (这是一个 big 简化并避免了处理冲突的复杂性)。键的查找只需要对键进行散列以找到值的位置(这是 O(1),而不是 O(n) 数组查找)。 R 列表使用 O(n) 的名称查找。

正如 Dirk 所说,使用 hash 包。一个巨大的限制是它使用环境(散列)并覆盖 [模拟哈希表的方法。但是一个环境不能包含另一个环境,因此您不能使用哈希函数嵌套哈希。

不久前,我致力于在 C/R 中实现一个可以嵌套的纯哈希表数据结构,但在我从事其他工作时,它在我的项目中落后了。不过要是有就好了:-)

关于r - 我可以在 R 中使用列表作为哈希吗?如果是这样,为什么这么慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3470447/

相关文章:

r - 在 R 中,如何合并两组拆分函数的结果?

R 使用样本创建具有随机数的矩阵列

r - 查找出现在另一个向量值范围内的向量值

regex - 多行正则表达式搜索

java - Java 中是否存在针对具有固定哈希长度的字符串的现成双向哈希函数?

重新列出各种深度的平面列表,保留类

perl - 使用Perl客户端-服务器(套接字)执行远程命令

perl - 如何在 Windows 上使用 perl 调用系统文件选择对话框?

perl - 保存 Perl Windows 环境 key UPCASES

node.js - 使用加密模块的流功能获取文件的哈希(即 : without hash. 更新和 hash.digest)