我想插入“&”在字母之间(大写和小写),但不是在字母之前或之后,并将每个小写字母x替换为tt $X == 0,每个大写字母X由tt $X == 1替换,并且每个by)|(,加上一个左括号和一个闭括号围绕整个字符串,以便得到一个可以用R计算的表达式.例如,我有字符串
st <- "AbC + de + FGHIJ"
结果应如下所示:
"(tt$A==1 & tt$B==0 & tt$C==1) | (tt$D==0 & tt$E==0) | (tt$F==1 & tt$G==1 & tt$H==1 & tt$I==1 & tt$J==1)"
我可以使用gsub()函数轻松完成吗?
解决方法
一堆正则表达式很少优雅,而且通常难以调试.如果元素之间没有精确的间距,则上述正则表达式解决方案会失败.
> tt("aBc+b") [1] "(tt$A==0 & tt$B==1 & tt$C==0+tt$B==0)" > tt("aBc + b") [1] "(tt$A==0 & tt$B==1 & tt$C==0) | (tt$B==0)"
有时您只需要自己拆分并处理它们.这是一个解决方案:
doChar = Vectorize( function(c){ sprintf("tt$%s==%s",toupper(c),ifelse(c %in% LETTERS,"1","0")) } ) doWord = Vectorize(function(W){ cs = strsplit(W,"")[[1]] paste0("(",paste(doChar(cs),collapse=" & "),")") }) processString = function(st){ parts = strsplit(st,"\\+")[[1]] parts = gsub(" ","",parts) paste0(doWord(parts),collapse=" | ") }
可能有很多方法可以让它变得更好,但它的好处是更容易调试(你可以测试部件)并且看起来不像线路噪音:)
对于给定的示例字符串,它返回与tt函数相同的函数,它是regexp解决方案的函数包装器:
> tt(st)==processString(st) [1] TRUE
但处理间距:
> processString("aBc + deF") == processString("aBc+deF") [1] TRUE
编写在它接受的输入中有点灵活的代码总是一个好主意.您可能还注意到输出元素的tt部分只出现一次,因此如果要输出foo $A而不是tt $A,则只需要进行一次更改.正则表达式解决方案在三个地方有这个(如果我错过了一个,可能有四个!).