Создание оператора конкатенации строк в R

Мне было интересно, как можно написать оператор конкатенации строк в R, что-то вроде || в SAS + в Java/C# или & в Visual Basic.

Самый простой способ - создать специальный оператор с использованием%, например

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

но это приводит к большому количеству уродливых %в коде.

Я заметил, что + определен в группе Ops, и вы можете написать S4-методы для этой группы, так что, возможно, что-то подобное может быть правильным. Тем не менее, у меня нет опыта работы с языком S4. Как бы я изменил вышеуказанную функцию, чтобы использовать S4?

5 ответов

Решение

Как уже упоминали другие, вы не можете переопределить запечатанный метод 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"

Это решение похоже на хак, поскольку вы больше не используете формальные методы, а единственный способ получить именно то поведение, которое вы хотели.

Я попробую это (относительно более чистое решение 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 в +

Вы также можете использовать классы 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

Если бы R полностью соответствовал S4, следующего было бы достаточно:

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

Но это дает ошибку, что метод запечатан:((. Надеюсь, это изменится в версиях функций R.

Лучшее, что вы можете сделать, это определить новый класс "string", который будет вести себя точно так же, как класс "персонажа"

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"

Вы дали себе правильный ответ - все в R является функцией, и вы не можете определить новые операторы. Так %+% так хорошо, как это возможно.

Другие вопросы по тегам