Перегрузка подстрочного оператора "["

Я пытаюсь перегрузить оператор индекса ("[") для пользовательского класса, который я создал. Я пытаюсь понять, как справиться со следующими проблемами.

  • Как вы можете выяснить, находится ли оператор на левом или правом ходу? т.е. 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 ответа

Решение

Для первой точки маркера есть две функции для перегрузки:

  1. [
  2. [<-

Первая функция возвращает значение, а вторая устанавливает значение. Смотрите документацию для 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 и т.п.

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