Создание оператора конкатенации строк в R
Мне было интересно, как можно было бы написать оператор конкатенации строк в R, что-то вроде || в SAS, + в Java/С# или или в Visual Basic.
Самый простой способ - создать специальный оператор, использующий%, например
`%+%` <- function(a, b) paste(a, b, sep="")
но это приводит к множеству уродливых %
в коде.
Я заметил, что +
определяется в группе Ops, и вы можете писать S4-методы для этой группы, поэтому, возможно, что-то вроде этого будет способом. Однако у меня нет опыта работы с языковыми функциями S4. Как изменить эту функцию для использования S4?
Ответы
Ответ 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 является функцией, и вы не можете определить новые операторы. Итак, %+%
так же хорош, как и он.