Подтвердить что ты не робот

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

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

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

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

но это приводит к множеству уродливых % в коде.

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

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

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

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"

Ответ 5

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