Creare un operatore di concatenazione di stringhe in R

Mi stavo chiedendo come si possa scrivere un operatore di concatenazione di stringhe in R, qualcosa come || in SAS, + in Java / C # o & in Visual Basic.

Il modo più semplice sarebbe creare un operatore speciale usando%, come

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

ma questo porta a molti brutti % nel codice.

Ho notato che + è definito nel gruppo Ops e puoi scrivere i metodi S4 per quel gruppo, quindi forse qualcosa del genere sarebbe la strada da percorrere. Tuttavia, non ho esperienza con le funzionalità del linguaggio S4. Come modifico la funzione sopra per usare S4?

Come altri hanno menzionato, non è ansible ignorare il metodo S4 sigillato “+”. Tuttavia, non è necessario definire una nuova class per definire una funzione di aggiunta per le stringhe; questo non è l’ideale dato che ti obbliga a convertire la class di stringhe e quindi a creare codice più brutto. Invece, si può semplicemente sovrascrivere la funzione “+”:

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

Quindi il seguente dovrebbe funzionare come previsto:

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

Questa soluzione sembra un po ‘un trucco, dal momento che non usi più metodi formali ma è l’unico modo per ottenere il comportamento esatto che volevi.

Puoi anche usare le classi S3 per questo:

 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 

Proverò questo (soluzione S3 relativamente più pulita)

 `+` <- 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') 

Il codice sopra cambierà + in un generico e imposterà il +.default sul + originale, quindi aggiungerà il nuovo metodo +.character a +

Se R fosse fedelmente conforms a S4, quanto segue sarebbe stato sufficiente:

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

Ma questo dà un errore che il metodo è sigillato: ((. Speriamo che questo cambierà nelle versioni di R.

Il meglio che puoi fare è definire una nuova “stringa” di class che si comporterebbe esattamente come una class “personaggio”:

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

e definire il metodo più generale che R consente:

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

ora prova:

 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" 

Ti sei dato la risposta corretta – tutto in R è una funzione e non puoi definire nuovi operatori. Quindi %+% è buono come diventa.