2011-01-19 54 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+