Перегрузка подстрочного оператора "["
Я пытаюсь перегрузить оператор индекса ("["
) для пользовательского класса, который я создал. Я пытаюсь понять, как справиться со следующими проблемами.
- Как вы можете выяснить, находится ли оператор на левом или правом ходу? т.е.
a[x] = foo
противfoo = a[x]
- При подписке всего измерения, как
foo = a[,x]
как я могу определить первый параметр? - При использовании [seq(x,y)] кажется, что он расширяет всю последовательность. Есть ли простой способ получить первое, шаг и последнее значение без расширения?
РЕДАКТИРОВАТЬ: мой первый пункт получил несколько ответов. В процессе я разобрался с ответом на второй. Вы можете использовать функцию "отсутствует", чтобы выяснить, какие параметры присутствуют.
Вот пример кода:
setMethod("[", signature(x="myClass"),
function(x, i, j, k, l) {
if (missing(i)) { i = 0 }
if (missing(j)) { j = 0 }
if (missing(k)) { k = 0 }
if (missing(l)) { l = 0 }
})
Я принял ответ на этот вопрос, поскольку пункт 3 является для меня наименее приоритетным.
4 ответа
Для первой точки маркера есть две функции для перегрузки:
[
[<-
Первая функция возвращает значение, а вторая устанавливает значение. Смотрите документацию для Extract.data.frame{base}
Откройте Generic, чтобы вы знали, что вы хотите реализовать:
getGeneric('[')
# standardGeneric for "[" defined from package "base"
# function (x, i, j, ..., drop = TRUE)
А также:
getGeneric('[<-')
# standardGeneric for "[<-" defined from package "base"
# function (x, i, j, ..., value)
Затем вы реализуете это, например, так:
`[<-.foo` <-
function(x, i, j, value)
{
....
}
Смотрите источник для [.data.frame
В качестве примера. У вас есть x, a i и a j в этом порядке.
> `[.data.frame`
function (x, i, j, ..... )
> `[<-.data.frame`
function (x, i, j, value)
Вы можете сделать что-то подобное:
obj <- structure(runif(10),class="myclass")
`[.myclass` <- function(x,i=NULL,j=NULL) {
message("First parameter is ", i, "\n")
message("Second parameter is ", j, "\n")
sum(x)
}
obj[c(1,2,3)]
`[<-.myclass` <- function(x,i=NULL,j=NULL,value) {
res <- unclass(x)
res[i] <- value
res
}
obj[1] <- 1
Заказ не имеет значения. Я и J будут правы:
2 -> obj[2]
> obj
[1] 1.0000000 2.0000000 0.3466835 0.3337749 0.4763512 0.8921983 0.8643395 0.3899895 0.7773207 0.9606180
Что касается третьего пункта, вы можете использовать что-то вроде этого:
seq_parse <- function(s) {
the_s <- deparse(substitute(s))
env <- new.env()
assign("seq", function(...) return(list(...)), envir=env)
seq_params <- try(eval(parse(text=the_s), envir=env), silent=TRUE)
if(!inherits(seq_params, "try-error")) {
cat("parsing successful \n")
return(seq_params)
} else {
stop("Failed to parse.")
}
}
Эта функция либо возвращает аргументы seq
,
> seq_parse(seq(from=1,to=10,by=0.5))
working with params to seq_params
$from
[1] 1
$to
[1] 10
$by
[1] 0.5
или обычный оцененный аргумент,
> seq_parse(1:5)
parsing successful
[1] 1 2 3 4 5
Однако я не уверен, что это хорошая практика. Также вы должны тщательно интерпретировать параметры seq
, они могут быть безымянными, и вместо to
может быть length.out
и т.п.