2011-01-19 107 views
36

我想知道一个会如何在R写入一个字符串连接运算符,像||在SAS中,在Java/C#中使用+或在Visual Basic中使用&。制作一个字符串连接运算符中的R

最简单的方法是创建使用%的特殊操作,如

`%+%` <- function(a, b) paste(a, b, sep="") 

但是这会导致大量的丑陋%的的代码。

我注意到在Ops组中定义了+,并且您可以为该组编写S4方法,因此可能需要类似这样的方法。但是,我根本没有使用S4语言功能的经验。我如何修改上述函数来使用S4?

+1

可能重复:http://stackoverflow.com/questions/1319698/why-doesnt-operate-on-characters-in-r – 2011-01-19 12:19:57

+2

HTTPS://stat.ethz。ch/pipermail/r-help/2005-February/066719.html – mdsumner 2011-05-31 14:33:54

回答

36

正如其他人所说,你不能覆盖密封S4方法 “+”。然而,你不需要定义一个新类来定义字符串的附加功能;这是不理想的,因为它迫使你转换字符串类,从而导致更难看的代码。相反,人们可以简单地覆盖了“+”功能:

"+" = function(x,y) { 
    if(is.character(x) || is.character(y)) { 
     return(paste(x , y, sep="")) 
    } else { 
     .Primitive("+")(x,y) 
    } 
} 

然后下面应该预计所有工作:

1 + 4 
1:10 + 4 
"Help" + "Me" 

该解决方案感觉有点像一个黑客,因为你不再使用形式方法,但它是获得你想要的确切行为的唯一方法。

8

你给自己正确的答案 - 一切都在R是一个函数,而不能定义新运算符。所以%+%是一样好。

+2

但是,您可以重新定义现有操作员的行为。不是在这种情况下,因为“+”方法对于签名c(“字符”,“字符”)是密封的。 – VitoshKa 2011-01-19 09:26:30

20

您还可以使用S3类这样的:

String <- function(x) { 
    class(x) <- c("String", class(x)) 
    x 
} 

"+.String" <- function(x,...) { 
    x <- paste(x, paste(..., sep="", collapse=""), sep="", collapse="") 
    String(x) 
} 


print.String <- function(x, ...) cat(x) 

x <- "The quick brown " 
y <- "fox jumped over " 
z <- "the lazy dog" 

String(x) + y + z 
11

若R将thoroghlly与S4遵守,以下就足够了:

setMethod("+", 
      signature(e1 = "character", e2 = "character"), 
      function (e1, e2) { 
       paste(e1, e2, sep = "") 
     }) 

但是,这给出了一个错误的方法((希望这会改变R的功能版本。)

你可以做的最好的是定义新的类“字符串”,其行为与“字符”类完全一样:

setClass("string", contains="character") 
string <- function(obj) new("string", as.character(obj)) 

,并定义最常用的方法,其中R允许:

setMethod("+", signature(e1 = "character", e2 = "ANY"), 
      function (e1, e2) string(paste(e1, as.character(e2), sep = ""))) 

现在就来试试:

tt <- string(44444) 

tt 
#An object of class "string" 
#[1] "44444" 
tt + 3434 
#[1] "444443434" 
"sfds" + tt 
#[1] "sfds44444" 
tt + tt 
#[1] "4444444444" 
343 + tt 
#Error in 343 + tt : non-numeric argument to binary operator 
"sdfs" + tt + "dfsd" 
#An object of class "string" 
#[1] "sdfs44444dfsd" 
+0

不需要S4,S3等价物很好。 – 2015-06-29 14:25:45

16

我会尝试这个(相对更干净S3溶液)以上

`+` <- function (e1, e2) UseMethod("+") 
`+.default` <- function (e1, e2) .Primitive("+")(e1, e2) 
`+.character` <- function(e1, e2) 
    if(length(e1) == length(e2)) { 
      paste(e1, e2, sep = '') 
    } else stop('String Vectors of Different Lengths') 

代码将改变+到一个通用的,并设置+.default原来的+,然后再添加新的方法来+.character+