假设我有一个像“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
和两个方法 pre
和 fun
。一开始 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/