2017-11-27 20 views
3

2つのリストに数字があり、1つのリストの値ともう1つのリストを一致させる必要があります。試合は番号の先頭に基づいて行われなければなりません。可能な限り最長一致のrow_idを返す必要があります。この例ではRの2つの整数の中で最も長いマッチを見つける

lookup value: 12345678 

find_list: 
a 1 
b 12 
c 123 
d 124 
e 125 
f 1234 
g 1235 

我々はa,b,c,fとの一致を持っているでしょうし、Rはfを返さなければなりません。 fは最長であり、したがって最もマッチします。

私は今、RでstartsWith関数を使用しています。その答えから、私は最も長い値を選択します。しかし、問題はリストが巨大であることです。 find_listに1850万のルックアップ値と300,000の可能な値があり、しばらくするとRがクラッシュします。

これを行うにはスマートな方法がありますか?

答えて

0

ここで、ベースR.内の1つの方法

# construct a vector of all possible matches for the lookup value 
lookupVec <- floor(lookup * (10^(-1 * (0:(nchar(lookup)-1))))) 

これはおそらく同じのパッケージからfastmatch機能をベースRのmatch機能を置き換えることで、これをスピードアップすることができ

lookupVec 
[1] 1234567 123456 12345 1234  123  12  1 

# find the value of the first variable that matches the maximum value 
# lower values in the vector 

dat$V1[which.min(match(dat$V2, lookupVec))] 
[1] f 
Levels: a b c d e f g 

を返すがあります名前を2回以上検索すると、テーブルの値がハッシュされるため、名前になります。

データ

dat <- 
structure(list(V1 = structure(1:7, .Label = c("a", "b", "c", 
"d", "e", "f", "g"), class = "factor"), V2 = c(1L, 12L, 123L, 
124L, 125L, 1234L, 1235L)), .Names = c("V1", "V2"), class = "data.frame", 
row.names = c(NA, -7L)) 

lookup <- 12345678 
0

は、たぶん、あなたが望むものをやってのよりスマートな方法がありますが、次は問題の結果を生成します。
パッケージstringiがインストールされている必要があります。
まず、質問のデータ。

lookup <- "12345678" 
find_list <- read.table(text = " 
a 1 
b 12 
c 123 
d 124 
e 125 
f 1234 
g 1235 
") 
find_list$V2 <- as.character(find_list$V2) 

コードが追加されました。ここで

inx <- which(stringi::stri_detect(lookup, regex = find_list$V2)) 
inx <- inx[which.max(nchar(find_list$V2[inx]))] 
find_list[inx, ] 
# V1 V2 
#6 f 1234 
0

あなたはdata.tableにあなたのfind_listを変換することができた場合のオプションです:

y <- 123456789 

x <- data.table(sample(1:1000000, 1000000, replace = T)) # find list 
n <- round(log(y, base = 10)) + 1 # number of digits 
z <- floor(y/(10^(1:(n)))) # split up into all possible integers 

x[V1 == x[V1 %in% z, max(.SD),],, which = T] 

これは、重複がある場合にも、複数の行IDを返します。行番号を返すだけでなく、返されるIDを持つ2番目の列を持つことができます。

2千万の整数のリストについては、1秒未満です。

Unit: seconds 
              expr  min   lq  mean  median   uq  max neval 
x[V1 == x[V1 %in% z, max(.SD), ], , which = T] 0.00076113 0.000871416 0.02571112 0.000945884 0.00109958 0.6195882 25 
1
find_list$X[which.max(sapply(find_list$find_list, function(myX) 
    attr(gregexpr(myX, lookup_value)[[1]], "match.length")))] 
#[1] "f" 

DATA

find_list = structure(list(X = c("a", "b", "c", "d", "e", "f", "g"), find_list = c(1L, 
12L, 123L, 124L, 125L, 1234L, 1235L)), .Names = c("X", "find_list" 
), class = "data.frame", row.names = c(NA, -7L)) 

lookup_value = 12345678 
関連する問題