如何提取2个字符串的不同部分

时间:2014-06-07 00:28:37

标签: string r

我有

x<-c('abczzzdef','abcxxdef')

我想要一个功能

fn(x)

返回长度为2的向量

[1] 'zzz' 'xx'

如何?

(我已尝试搜索答案,但搜索条件如“部分匹配&#39;给我一些完全不同的内容”

更新

&#39;长度为2的向量&#39;表示length(fn(x))2fn(x)[1]表示"zzz"fn(x)[2]表示"xx"。 在尝试了所提供的答案后,我意识到我还不够具体。

  • 我将比较只有2个字符串(在向量中)。
  • 不同部分(zzz和xx)的位置可以是字符串中的任何位置。即它可能是x<-c('zzzabcdef','xxabcdef')或者它可能在最后。但是2个字符串总是在相同的位置(即在开头,或者在中间,或者在结尾都是)。
  • zzzxx显然是通用名称。它们可以是不同的东西(数字,字母,符号)和不同的长度(不一定是3和2)。
  • 同样的评论适用于abcdef

我有一些测试用例

x1<-c('abcxxxttt','abczzttt')
x2<-c('abcxxxdef','abczz126gsdef')
x3<-c('xx_x123../t','z_z126gs123../t') 

fn(x1)应该"xxx" "zz"

fn(x2)应该"xxx" "zz126gs"

fn(x3)应该"xx_x" "z_z126gs"

3 个答案:

答案 0 :(得分:1)

x<-c('abczzzdef','abcxxdef')
fn <- function(x) unlist(regmatches(x, gregexpr("(.)\\1+", x)))
fn(x)
# [1] "zzz" "xx" 

答案 1 :(得分:1)

首先,在问题的第一个版本中包含所有细节会更好。没有必要浪费时间,因为你没有清楚地解释你需要什么,所以不得不花时间提出不适合你的解决方案。如果您在问题得到解答之后需要更改一个问题,那么最好提出一个新问题,而不是完全改变第一个问题。

你要做的事情,找到字符串中最大的非共享部分,对于计算机来说可能是一个非常混乱的过程。字符串不相似性的某种标准度量是R在adist函数中实现的广义Levenshtein距离。它可以生成一个字符串,告诉您如何通过匹配,插入,删除和替换将一个字符串转换为另一个字符串。如果我找到最长的匹配字符串,我会非常清楚在哪里提取唯一信息。

因此,该方法主要侧重于提取最佳匹配之外的区域。这是匹配

的功能
fn <- function(x) {
    ld <- attr(adist(x[1], x[2], counts=T, 
        costs=c(substitutions=500)),"trafos")[1,1]
    starts <- gregexpr("M+", ld)[[1]]
    lens <- attr(starts,"match.length")
    starts <- as.vector(starts)
    ends <- starts + lens - 1
    bm <- which.max(lens)
    if (starts[bm]==1 | ends[bm]==nchar(ld)) {
        #beg/end
        for( i in which(starts==1 | ends==nchar(ld))) {
            substr(ld, starts[i], ends[i]) <- 
                paste(rep("X", lens[i]), collapse="")
        }
    } else {
        #middle
        substr(ld, starts[bm], ends[bm]) <- 
            paste(rep("X", lens[bm]), collapse="")
    }
    tr <- strsplit(ld,"")[[1]]
    x1 <- cumsum(tr %in% c("D","M","X"))[!tr %in% c("X","I")]
    x2 <- cumsum(tr %in% c("I","M","X"))[!tr %in% c("X","D")]
    c(substr(x[1], min(x1), max(x1)), substr(x[2], min(x2), max(x2)))
}

现在我们可以将它应用于您的测试数据

x1 <- c('abcxxxttt','abczzttt')
x2 <- c('abcxxxdef','abczz126gsdef')
x3 <- c('xx_x123../t','z_z126gs123../t') 

fn(x1)
# [1] "xxx" "zz" 
fn(x2)
# [1] "xxx"     "zz126gs"
fn(x3)
# [1] "xx_x"     "z_z126gs"

所以我们得到你期望的结果。在这里,我做了一些错误检查。我假设总会有一些重叠和一些不重叠的区域。如果不成立,则该功能可能会产生错误或意外结果。

答案 2 :(得分:0)

 gsub("([^xz]*)([xz]*)([^xz]*)", "\\2", x)
[1] "zzz" "xx" 

> getxz <- function(x, str) gsub(paste0("([^",str, ']*)([', str, ']*)([^', str, ']*)'),
                                 "\\2", x)
> getxz(x=x,"xz")
[1] "zzz" "xx" 

为了回应新的例子,我提供了这些测试,我认为这些测试有三个成功:

> getxz(x=x1,"xz_")
[1] "xxx" "zz" 
> getxz(x=x2,"xz_")
[1] "xxx" "zz" 
> getxz(x=x3,"xz_")
[1] "xx_x" "z_z"