我有一个函数返回两个字符串中最长的公共子字符串:
longest.substring <-function(a,b)
{
A <- strsplit(a, "")[[1]]
B <- strsplit(b, "")[[1]]
L <- matrix(0, length(A), length(B))
ones <- which(outer(A, B, "=="), arr.ind = TRUE)
ones <- ones[order(ones[, 1]), ]
if(length(ones)!=0){
for(i in 1:nrow(ones)) {
v <- ones[i, , drop = FALSE]
L[v] <- ifelse(any(v == 1), 1, L[v - 1] + 1)
}
paste0(A[(-max(L) + 1):0 + which(L == max(L), arr.ind = TRUE)[1]], collapse = "")
}
}
longest.substring("hello world","hella old") #returns "hell"
longest.substring("abc","def") #returns nothing
最初在Identify a common pattern中找到,我添加了if子句来处理根本没有子串匹配的字符串。它的工作正常,如代码中的示例所示,但我将问题应用于我的数据集时遇到了问题。对于它的每一行,我想在两列的值上使用此函数,并将结果输入第三列。我试了几次,例如:
table1$LCS <- mapply(longest.substring, table1$col1, table1$col2)
table1$LCS <- apply(table1[,c("col1","col2")], 1, function(x)
longest.substring(x["col1"],x["col2"]))
两种方式(我使用mapply
在这些列之间运行adist
并且工作正常)返回错误:
Error in 1:nrow(ones) : argument of length 0
从我在两个字符串上运行它的测试,这正是我添加if
之前发生的事情,所以函数'省略'这个子句并尝试运行导致错误的for
。 / p>
另外我想注意我的数据集非常大(几千行),所以我认为for
循环需要很长时间才能完成。
编辑也使for
循环,但它返回与上面相同的错误。
for (i in 1:nrow(Adresy_baza_match)){
Adresy_baza_match[i,"LCS"] <- longest.substring(Adresy_baza_match[i,4], Adresy_baza_match[i,5])
}
编辑我设法隔离哪一行导致错误:
a b
921 BRUSKIEGO PLATYNOWA
922 BRUSKIEGO BPAHIERONIMAROZRAŻEWSKIEGO
923 BRUSKIEGO BPAKONSTANTYNADOMINIKA
第一行似乎导致它:
x <-longest.substring("BRUSKIEGO", "PLATYNOWA")
在这种情况下(逐行length(ones)
运行功能代码为2,而nrow(ones)
返回NULL
,每次只有一个匹配时,我会发生其他尝试substring,它由一个char组成。
答案 0 :(得分:1)
有几点:
问题代码中的这一行:
ones <- ones[order(ones[, 1]), ]
应该是:
ones <- ones[order(ones[, 1]), , drop = FALSE ]
定义longest.substring.vec
,类似于longest.substring
,但它接受 vector a
和b
,而不仅仅是标量< / em>的。它还强制其对字符的参数,并用NA替换NULL,以确保结果是字符向量而不是列表。现在试试这个:
longest.substring.vec <- function(a, b, default = NA_character_,
USE.NAMES = FALSE) {
a <- as.character(a)
b <- as.character(b)
m <- mapply(longest.substring, a, b, USE.NAMES = USE.NAMES)
m[lengths(m) == 0] <- default
unlist(m)
}
测试这两项变化:
tab <- data.frame(a = c("hello, world", "abc"), b = c("hella old", "def"))
transform(tab, c = longest.substring.vec(a, b))
## a b c
## 1 hello, world hella old hell
## 2 abc def <NA>
<强>更新强>
添加了第1点。重新排列的演示文稿。
答案 1 :(得分:1)
GrpString
包提供了一个更简单、更强大的解决方案。
s <- c("hello world","hello old", "hello")
GrpString::CommonPatt(s) %>%
filter(Freq_str == length(s)) %>% filter(Length == max(Length)) %>%
select(Pattern) %>% unlist(use.names = F)
检查 GrpString::CommonPatt(s)
的输出以获取有关常见模式的更多信息