Создание оператора конкатенации строк в 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 является функцией, и вы не можете определить новые операторы. Так %+%
так хорошо, как это возможно.