这个问题只是要求在R中实现以下问题:Find the longest common starting substring in a set of strings(JavaScript)
“此问题是最长公共子字符串问题的一个更具体的情况。我只需要找到数组中最长的公共起始子字符串”。
所以我只是在寻找这个问题的R实现(最好不要在JavaScript版本中建议的 for / while循环方式),如果可能的话我想把它包装成一个函数,所以我可以应用于数据表中的许多组。
经过一些搜索,我找不到一个R的例子,因此这个问题。
示例数据: 我有以下字符向量:
dput(data)
c("ADA4417-3ARMZ-R7", "ADA4430-1YKSZ-R2", "ADA4430-1YKSZ-R7",
"ADA4431-1YCPZ-R2", "ADA4432-1BCPZ-R7", "ADA4432-1BRJZ-R2")
我希望在R 中运行一个算法,它会找到以下输出:ADA44
。
从我在JavaScript接受的答案中看到的,我们的想法是先对矢量进行排序,提取第一个和最后一个元素(例如:"ADA4417-3ARMZ-R7"
和"ADA4432-1BRJZ-R2"
,将它们分解为单个字符,并循环通过它们,直到其中一个字符不匹配(希望我正确)
任何帮助都会很棒!
答案 0 :(得分:7)
从你的建议中汲取灵感,你可以尝试这个功能:
comsub<-function(x) {
# sort the vector
x<-sort(x)
# split the first and last element by character
d_x<-strsplit(x[c(1,length(x))],"")
# compute the cumulative sum of common elements
cs_x<-cumsum(d_x[[1]]==d_x[[2]])
# check if there is at least one common element
if(cs_x[1]!=0) {
# see when it stops incrementing and get the position of last common element
der_com<-which(diff(cs_x)==0)[1]
# return the common part
return(substr(x[1],1,der_com))
} else { # else, return an empty vector
return(character(0))
}
}
更新
遵循@nicola建议,该功能更简单,更优雅的变体:
comsub<-function(x) {
# sort the vector
x<-sort(x)
# split the first and last element by character
d_x<-strsplit(x[c(1,length(x))],"")
# search for the first not common element and so, get the last matching one
der_com<-match(FALSE,do.call("==",d_x))-1
# if there is no matching element, return an empty vector, else return the common part
ifelse(der_com==0,return(character(0)),return(substr(x[1],1,der_com)))
}
示例:
使用您的数据
x<-c("ADA4417-3ARMZ-R7", "ADA4430-1YKSZ-R2", "ADA4430-1YKSZ-R7",
"ADA4431-1YCPZ-R2", "ADA4432-1BCPZ-R7", "ADA4432-1BRJZ-R2")
> comsub(x)
#[1] "ADA44"
当没有共同的起始子串
时x<-c("abc","def")
> comsub(x)
# character(0)
答案 1 :(得分:4)
非base
替代方案,使用lcprefix
中的Biostrings
函数查找“两个字符串的最长公共前缀[...]”
source("http://bioconductor.org/biocLite.R")
biocLite("Biostrings")
library(Biostrings)
x2 <- sort(x)
substr(x2[1], start = 1, stop = lcprefix(x2[1], x2[length(x2)]))
# [1] "ADA44"
答案 2 :(得分:0)
根据Henrik的回答,Bioconductor具有基于C的前缀功能和基于R的前缀功能。基于R的是:
lcPrefix <- function (x, ignore.case = FALSE)
{
x <- as.character(x)
if (ignore.case)
x <- toupper(x)
nc <- nchar(x, type = "char")
for (i in 1:min(nc)) {
ss <- substr(x, 1, i)
if (any(ss != ss[1])) {
return(substr(x[1], 1, i - 1))
}
}
substr(x[1], 1, i)
}
<environment: namespace:Biobase>
...并且不需要Bioconductor的任何特殊功能(据我所知)。
---引文---
使用Bioconductor编排高通量基因组分析。 W. Huber,V.J。 Carey,R。Gentleman,...,M。Morgan Nature Methods,
2015:12,115。
答案 3 :(得分:0)
这是一个紧凑的解决方案:
data<-c("ADA4417-3ARMZ-R7", "ADA4430-1YKSZ-R2", "ADA4430-1YKSZ-R7", "ADA4431-1YCPZ-R2", "ADA4432-1BCPZ-R7", "ADA4432-1BRJZ-R2")
substr(data[1],1,which.max(apply(do.call(rbind,lapply(strsplit(data,''),`length<-`,nchar(data[1]))),2,function(i)!length(unique(i))==1))-1)
[1] "ADA44"