【问题标题】:Extract characters that differ between two strings提取两个字符串之间不同的字符
【发布时间】:2015-05-04 06:15:49
【问题描述】:

我已经使用adist 来计算两个字符串之间不同的字符数:

a <- "Happy day"
b <- "Tappy Pay"
adist(a,b) # result 2

现在我想提取那些不同的字符。在我的例子中,我想得到字符串"Hd"(或者"TP",没关系)。

我尝试查看adistagrepstringi,但一无所获。

【问题讨论】:

  • 我建议您撤消编辑并提出一个新问题。在这个新问题中,您必须提供有关您的真实数据的更多信息。例如,您是否知道不同的字符串位于字符串的开头和结尾,这一点非常重要。您还必须告诉我们您的问题是否与longest common substring problem 有关。
  • 同意,撤消编辑,接受最佳答案,然后提出新问题。这个问题本质上是不同的,很多人已经投入了大量的工作。

标签: r string character


【解决方案1】:

只要ab 的长度相同,我们就可以这样做:

s.a <- strsplit(a, "")[[1]]
s.b <- strsplit(b, "")[[1]]
paste(s.a[s.a != s.b], collapse = "")

给予:

[1] "Hd"

就代码的清晰度而言,这似乎很简单,并且似乎与此处提供的最快解决方案相关,尽管我认为我更喜欢f3

f1 <- function(a, b)
  paste(setdiff(strsplit(a,"")[[1]],strsplit(b,"")[[1]]), collapse = "")

f2 <- function(a, b)
  paste(sapply(setdiff(utf8ToInt(a), utf8ToInt(b)), intToUtf8), collapse = "")

f3 <- function(a, b) 
  paste(Reduce(setdiff, strsplit(c(a, b), split = "")), collapse = "")

f4 <- function(a, b) {
  s.a <- strsplit(a, "")[[1]]
  s.b <- strsplit(b, "")[[1]]
  paste(s.a[s.a != s.b], collapse = "")
}

a <- "Happy day"
b <- "Tappy Pay"

library(rbenchmark)
benchmark(f1, f2, f3, f4, replications = 10000, order = "relative")[1:4]

在我的笔记本电脑上进行新会话:

  test replications elapsed relative
3   f3        10000    0.07    1.000
4   f4        10000    0.07    1.000
1   f1        10000    0.09    1.286
2   f2        10000    0.10    1.429

我假设差异必须在相应的字符位置。您可能想澄清这是否是意图。

【讨论】:

    【解决方案2】:

    对此并不感到自豪,但它似乎可以胜任:

    sapply(setdiff(utf8ToInt(a), utf8ToInt(b)), intToUtf8)
    

    结果:

    [1] "H" "d"
    

    【讨论】:

    • 这个不错。您可能可以通过 intToUtf8(setdiff(utf8ToInt(a), utf8ToInt(b))) 对其进行矢量化
    【解决方案3】:

    拆分成字母,取差为集:

    > setdiff(strsplit(a,"")[[1]],strsplit(b,"")[[1]])
    [1] "H" "d"
    

    【讨论】:

      【解决方案4】:

      您可以使用以下操作顺序:

      • 使用strsplit()分割字符串。
      • 使用setdiff()比较元素
      • 包装在一个归约函数中

      试试这个:

      Reduce(setdiff, strsplit(c(a, b), split = ""))
      [1] "H" "d"
      

      【讨论】:

      • do.call(setdiff, strsplit(c(a, b), split = "")) 可能会更高效
      • 第二个参数到strsplitsplit,所以如果你想在更少的镜头中倒下,你不需要命名它。
      • @DavidArenburg 如果您正在玩代码高尔夫,则不会。 Reducedo.call 少一键击键 :-)
      • @Spacedman 随着编程问题答案数量的增加,它退化为代码高尔夫的概率接近 1。
      【解决方案5】:

      您可以将其中一个变量用作正则表达式字符类,并从另一个变量中取出gsub

      gsub(paste0("[",a,"]"),"",b)
      [1] "TP"
      gsub(paste0("[",b,"]"),"",a)
      [1] "Hd"
      

      【讨论】:

      • 如果字符串中包含正则表达式特殊字符,这是否有效?
      • @Spacedman 是的,很好,特殊字符类正则表达式,例如^- 可能会导致问题。这可能是连字符的特殊问题。
      【解决方案6】:

      以下函数可能是解决此类问题的更好选择。

      list.string.diff <- function(a, b, exclude = c("-", "?"), ignore.case = TRUE, show.excluded = FALSE)
      {
      if(nchar(a)!=nchar(b)) stop("Lengths of input strings differ. Please check your input.")
      if(ignore.case)
      {
      a <- toupper(a)
      b <- toupper(b)
      }
      split_seqs <- strsplit(c(a, b), split = "")
      only.diff <- (split_seqs[[1]] != split_seqs[[2]])
      only.diff[
      (split_seqs[[1]] %in% exclude) |
      (split_seqs[[2]] %in% exclude)
      ] <- NA
      diff.info<-data.frame(which(is.na(only.diff)|only.diff),
      split_seqs[[1]][only.diff],split_seqs[[2]][only.diff])
      names(diff.info)<-c("position","poly.seq.a","poly.seq.b")
      if(!show.excluded) diff.info<-na.omit(diff.info)
      diff.info
      

      来自https://www.r-bloggers.com/extract-different-characters-between-two-strings-of-equal-length/

      然后就可以运行了

      list.string.diff(a, b)
      

      为了区别。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-11
        • 2019-10-10
        相关资源
        最近更新 更多