- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想进行非常快速的搜索,看来使用哈希(通过环境)是最好的方法。现在,我得到了一个在环境中运行的示例,但它没有返回我需要的内容。
这是一个例子:
a <- data.table::data.table(a=c(1, 3, 5), b=c(2, 4, 6), time=c(10, 20, 30))
my_env <- list2env(a)
x <- a[2, .(a, b)] # x=c(3,4)
found <- get("x", envir = my_env)
我希望 found = c(3, 4, 20)
但收到 found = c(3, 4)
(我希望返回整行而不是未知的行子集)
背景:我有一个巨大的列表,其中包含使用 osrm 计算的路由的源和目的地,例如
lattitude1, longitude1, lattitude2, longitude2, travel-time
46.12, 8.32, 47.87, 9.92, 1036
...
该列表在第一个示例中包含大约 100000 行。在 data.table 中使用二进制搜索将我的代码速度提高了 100 倍,但一次搜索仍需要 1 毫秒。因为我必须在模拟过程中搜索很多路线(大约 2e5 次搜索),所以我想变得更快。
@Gregor:我是 R 的初学者,但我不认为我的问题是重复的:
总结(感谢 DigEmAll 下面的运行示例):
最佳答案
下面是一个使用环境和 data.table 的例子,代码是不言自明的:
library(data.table)
# create a big random example (160k rows)
set.seed(123)
fromTo <- expand.grid(1:400,1:400)
colnames(fromTo) <- c('a','b')
DF <- as.data.frame(cbind(fromTo,time=as.integer(runif(nrow(fromTo), min = 1, max=500))))
# setup the environment to use it as hashtable:
# we simply put the times inside an enviroment using
# a|b (concatenation of a with b) as key
timesList <- as.list(DF$time)
names(timesList) <- paste(DF$a,DF$b,sep='|')
timesEnv <- list2env(timesList)
# setup the data.table to use it as hashtable
DT <- setDT(DF,key=c('a','b'))
# create search functions
searchUsingEnv <- function(a,b){
time <- get(paste(a,b,sep='|'),envir=timesEnv,inherits=FALSE)
return(time)
}
searchUsingDataTable <- function(from,to){
time <- DT[.(from,to),time]
return(time)
}
基准:
# benchmark functions
# i.e. we try to search ~16K rows in ourtwo kind of hashtables
benchEnv <- function(){
n <- nrow(fromTo)
s <- as.integer(n * 0.9)
for(i in s:n){
searchUsingEnv(fromTo[i,'a'],fromTo[i,'b'])
}
}
benchDT <- function(){
n <- nrow(fromTo)
s <- as.integer(n * 0.9)
for(i in s:n){
searchUsingDataTable(fromTo[i,'a'],fromTo[i,'b'])
}
}
# let's measure the performances
> system.time(benchEnv(), gcFirst = TRUE)
user system elapsed
2.26 0.00 2.30
> system.time(benchDT(), gcFirst = TRUE)
user system elapsed
42.34 0.00 42.56
结论:
环境似乎比 data.table 重复单键访问快得多,所以你可以尝试使用它。
环境可以快速访问,但它们只能有占用比 double 更多内存的字符串键。所以,我添加了一个使用 Rcpp
的示例和 std::map<>
使用多值映射:
(注意:如果您使用的是 Windows,则需要安装 RTools 才能使 Rcpp 正常工作)
library(data.table)
library(Rcpp)
library(inline)
nRows <- 1e7
############# create data.table "DT" containing coordinates and times
generate_routes_dt <- function(nmax) {
set.seed(123)
routes <- data.table(lat1 = numeric(nmax),
lng1 = numeric(nmax),
lat2 = numeric(nmax),
lng2 = numeric(nmax),
time = numeric(nmax))
tmp <- sample(seq(46, 49, length.out = nmax), nmax)
routes$lat1 <- tmp
tmp <- sample(seq(8, 10, length.out = nmax), nmax)
routes$lng1 <- tmp
tmp <- sample(seq(46, 49, length.out = nmax), nmax)
routes$lat2 <- tmp
tmp <- sample(seq(8, 10, length.out = nmax), nmax)
routes$lng2 <- tmp
tmp <- sample(seq(0, 1e7, length.out = nmax), nmax)
routes$time <- as.integer(tmp)
data.table::setkey(routes, lat1, lng1, lat2, lng2)
return(routes)
}
DT <- generate_routes_dt(nRows)
############# create data.table search function
searchUsingDataTable <- function(lat_1,lng_1,lat_2,lng_2){
time <- DT[.(lat_1,lng_1,lat_2,lng_2),time]
return(time)
}
#############
############# create Rcpp search function
# the following code create 2 functions: createMap and getTime
# usage:
# map <- createMap(lat1Vec,lng1Vec,lat2Vec,lng2Vec,timesVec)
# t <- getTime(map,lat1,lng1,lat2,lng2)
sourceCpp(code=
'
#include <Rcpp.h>
class MultiKey {
public:
double lat1;
double lng1;
double lat2;
double lng2;
MultiKey(double la1, double ln1, double la2, double ln2)
: lat1(la1), lng1(ln1), lat2(la2), lng2(ln2) {}
bool operator<(const MultiKey &right) const
{
if ( lat1 == right.lat1 ) {
if ( lng1 == right.lng1 ) {
if ( lat2 == right.lat2 ) {
return lng2 < right.lng2;
}
else {
return lat2 < right.lat2;
}
}
else {
return lng1 < right.lng1;
}
}
else {
return lat1 < right.lat1;
}
}
};
// [[Rcpp::export]]
SEXP createMap(Rcpp::NumericVector lat1,
Rcpp::NumericVector lng1,
Rcpp::NumericVector lat2,
Rcpp::NumericVector lng2,
Rcpp::NumericVector times){
std::map<MultiKey, double>* map = new std::map<MultiKey, double>;
int n1 = lat1.size();
int n2 = lng1.size();
int n3 = lat2.size();
int n4 = lng2.size();
int n5 = times.size();
if(!(n1 == n2 && n2 == n3 && n3 == n4 && n4 == n5)){
throw std::range_error("input vectors lengths are different");
}
for(int i = 0; i < n1; i++){
MultiKey key(lat1[i],lng1[i],lat2[i],lng2[i]);
map->insert(std::pair<MultiKey, double>(key, times[i]));
}
Rcpp::XPtr< std::map<MultiKey, double> > p(map, true);
return( p );
}
// [[Rcpp::export]]
Rcpp::NumericVector getTime(SEXP mapPtr,
double lat1,
double lng1,
double lat2,
double lng2){
Rcpp::XPtr< std::map<MultiKey, double> > ptr(mapPtr);
MultiKey key(lat1,lng1,lat2,lng2);
std::map<MultiKey,double>::iterator it = ptr->find(key);
if(it == ptr->end())
return R_NilValue;
return Rcpp::wrap(it->second);
}
')
map <- createMap(DT$lat1,DT$lng1,DT$lat2,DT$lng2,DT$time)
searchUsingRcpp <- function(lat_1,lng_1,lat_2,lng_2){
time <- getTime(map,lat_1,lng_1,lat_2,lng_2)
return(time)
}
#############
############# benchmark
set.seed(1234)
rowsToSearchOneByOne <- DT[sample.int(nrow(DT),size=nrow(DT),replace=FALSE),]
bench <- function(searchFun2Use){
for(i in nrow(rowsToSearchOneByOne)){
key <- rowsToSearchOneByOne[i,]
searchFun2Use(key$lat1,key$lng1,key$lat2,key$lng2)
}
}
microbenchmark::microbenchmark(
bench(searchUsingRcpp),
bench(searchUsingDataTable),
times=100)
#############
基准测试结果:
Unit: microseconds
expr min lq mean median uq max neval
bench(searchUsingRcpp) 360.959 381.7585 400.4466 391.999 403.9985 665.597 100
bench(searchUsingDataTable) 1103.034 1138.0740 1214.3008 1163.514 1224.9530 2035.828 100
注意:
我真的不认为使用 double 作为键是个好主意...浮点值应该用于使用特定容差或在范围内进行搜索,而不是在 map 中查找完美匹配。
关于R:列表中的快速哈希搜索(环境),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37026669/
我正在尝试 grep conf 文件中所有不以 开头的有效行 哈希(或) 任意数量的空格(0 个或多个)和一个散列 下面的正则表达式似乎不起作用。 grep ^[^[[:blank:]]*#] /op
我正在使用哈希通过 URL 发送 protected 电子邮件以激活帐户 Hash::make($data["email"]); 但是哈希结果是 %242y%2410%24xaiB/eO6knk8sL
我是 Perl 的新手,正在尝试从文本文件创建散列。我有一个代码外部的文本文件,旨在供其他人编辑。前提是他们应该熟悉 Perl 并且知道在哪里编辑。文本文件本质上包含几个散列的散列,具有正确的语法、缩
我一直在阅读 perl 文档,但我不太了解哈希。我正在尝试查找哈希键是否存在,如果存在,则比较其值。让我感到困惑的是,我的搜索结果表明您可以通过 if (exists $files{$key}) 找到
我遇到了数字对映射到其他数字对的问题。例如,(1,2)->(12,97)。有些对可能映射到多个其他对,所以我真正需要的是将一对映射到列表列表的能力,例如 (1,2)->((12,97),(4,1))。
我见过的所有 Mustache 文档和示例都展示了如何使用散列来填充模板。我有兴趣去另一个方向。 EG,如果我有这个: Hello {{name}} mustache 能否生成这个(伪代码): tag
我正在尝试使用此公式创建密码摘要以获取以下变量,但我的代码不匹配。不确定我做错了什么,但当我需要帮助时我会承认。希望有人在那里可以提供帮助。 文档中的公式:Base64(SHA1(NONCE + TI
我希望遍历我传递给定路径的这些数据结构(基本上是目录结构)。 目标是列出根/基本路径,然后列出所有子 path s 如果它们存在并且对于每个子 path存在,列出 file从那个子路径。 我知道这可能
我希望有一个包含对子函数的引用的散列,我可以在其中根据用户定义的变量调用这些函数,我将尝试给出我正在尝试做的事情的简化示例。 my %colors = ( vim => setup_vim()
我注意到,在使用 vim 将它们复制粘贴到文件中后尝试生成一些散列时,散列不是它应该的样子。打开和写出文件时相同。与 nano 的行为相同,所以一定有我遗漏的地方。 $ echo -n "foo"
数组和散列作为状态变量存在限制。从 Perl 5.10 开始,我们无法在列表上下文中初始化它们: 所以 state @array = qw(a b c); #Error! 为什么会这样?为什么这是不允
在端口 80 上使用 varnish 5.1 的多网站设置中,我不想缓存所有域。 这在 vcl_recv 中很容易完成。 if ( req.http.Host == "cache.this.domai
基本上,缓存破坏文件上的哈希不会更新。 class S3PipelineStorage(PipelineMixin, CachedFilesMixin, S3BotoStorage): pa
eclipse dart插件在“变量” View 中显示如下内容: 在“值”列中可见的“id”是什么意思? “id”是唯一的吗?在调试期间,如何确定两个实例是否相同?我是否需要在所有类中重写toStr
如何将Powershell中的命令行参数读入数组?就像是 myprogram -file file1 -file file2 -file file3 然后我有一个数组 [file1,file2,fil
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
例如,我有一个包含 5 个元素的哈希: my_hash = {a: 'qwe', b: 'zcx', c: 'dss', d: 'ccc', e: 'www' } 我的目标是每次循环哈希时都返回,但没
我在这里看到了令人作呕的类似问题,但没有一个能具体回答我自己的问题。 我正在尝试以编程方式创建哈希的哈希。我的问题代码如下: my %this_hash = (); if ($user_hash{$u
我正尝试在 coldfusion 中为我们的安全支付网关创建哈希密码以接受交易。 很遗憾,支付网关拒绝接受我生成的哈希值。 表单发送交易的所有元素,并发送基于五个不同字段生成的哈希值。 在 PHP 中
这个问题已经有答案了: Java - how to convert letters in a string to a number? (9 个回答) 已关闭 7 年前。 我需要一种简短的方法将字符串转
我是一名优秀的程序员,十分优秀!