假设我有一个像“C5Cl2NO2S”这样的分子式,我想用 R 计算它的分子量。我虽然最简单的方法是使用正则表达式,将公式分析并拆分为它的基本组件,然后将它们交给执行计算的单独函数。但是,我面临的问题是,当我交出 RegEx 的反向引用时,它们不会被评估,而是作为“\\1”、“\\2”提交。

这是我的尝试:

masses <- list(
  C  = 12,
  H  = 1.01,
  Cl = 34.97,
  N  = 14.00,
  O  = 15.99,
  P  = 30.97,
  S  = 31.97
)

elementMass <- function( element, count ) {
  if( count == "" ) {
    count <- "1"
  }
  return( as.character( masses[[ element ]] * as.numeric( count ) ) )
}


sumFormula2Mass <- function( x ){
  y <- 0.0
  for( e in x ) {
    if( e != "" ) {
      y <- y + as.numeric( sub( "^(C|H|Cl|N|O|P|S)([0-9]*)$", elementMass("\\1", "\\2"), e ) )
    }
  }
  return( y )
}

sub(
  "^(C[0-9]*)?(H[0-9]*)?(Cl[0-9]*)?(N[0-9]*)?(O[0-9]*)?(P[0-9]*)?(S[0-9]*)?$",
  sumFormula2Mass( c("\\1", "\\2", "\\3", "\\4", "\\5", "\\6", "\\7") ),
  "C5Cl2NO2S"
)

任何想法如何改善这一点?
非常感谢

最佳答案

下面我们假设问题中的公式形式,即一串组件,每个组件都是一个大写字母,后跟可选的小写字母,后跟可选的数字。我们在 gsubfn 包中使用 gsubfn。除了替换字符串可以是各种其他对象之外,它就像 gsub 。这是一个原型(prototype)对象。 proto 对象是一个环境,在这里它用于包含属性 sum 和两个方法 prefun 。一开始 pre 会自动运行,起到初始化 sum 的作用。然后每次正则表达式匹配时,proto 对象和两个引用的字符串被传递给 fun 并运行 fun 来处理它们。最后 p$sum 包含结果。变量 masses 在问题中定义。

library(gsubfn)
p <- proto(pre = function(this) this$sum <- 0,
    fun = function(this, name, count) {
        count <- as.numeric(count)
        if (is.na(count)) count <- 1
        this$sum <- this$sum + masses[[name]] * count
        ""
    })
gsubfn("([[:upper:]][[:lower:]]*)(\\d*)", p, "C5Cl2NO2S")
p$sum # 207.89

关于regex - sub() : Handling of backreferences,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7012455/

10-12 19:48