Оператор перегрузки нижнего индекса [

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

  • Как узнать, находится ли оператор слева или справа? то есть a[x] = foo против foo = a[x]
  • При подписке всего измерения, такого как foo = a[,x], как я могу определить первый параметр?
  • При использовании a[seq(x,y)] кажется, что вся последовательность расширяется. Есть ли простой способ получить первое, шаговое и последнее значения без расширения?

EDIT: Мой первый вопрос получил несколько ответов. В процессе я нашел ответ на второй. Вы можете использовать функцию «отсутствует», чтобы выяснить, какие параметры присутствуют.

Вот пример кода:

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 является для меня наименее приоритетным.


person Pavan Yalamanchili    schedule 14.03.2014    source источник
comment
По третьему пункту: это можно сделать, разобрав выражение, но это звучит немного удивительно (поведение a[seq(x, y)] и v = seq(x, y); a[v] будет другим)   -  person David Robinson    schedule 14.03.2014
comment
@DavidRobinson Можете ли вы подробнее рассказать о том, что вы подразумеваете под parsing the expression?   -  person Pavan Yalamanchili    schedule 14.03.2014


Ответы (4)


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

  1. [
  2. [<-

Первая функция возвращает значение, а вторая устанавливает значение. См. документацию для Extract.data.frame{base}

person f.jamitzky    schedule 14.03.2014

Откройте для себя 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) 
{
       ....

}
person agstudy    schedule 14.03.2014

См. источник для [.data.frame в качестве примера. У вас есть x, i и 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

Порядок не имеет значения. I и 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
person Ari B. Friedman    schedule 14.03.2014

Что касается третьего пункта, вы можете использовать что-то вроде этого:

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 и т.д.

person Karsten W.    schedule 14.03.2014