Каков наилучший способ удаления элемента из списка объектов в R - PullRequest
0 голосов
/ 08 апреля 2020

Играя с эталонными классами в R, я столкнулся с чем-то, что не очень красиво. Если у меня есть список объектов, есть ли способ удалить отдельный элемент из этого списка, который не включает в себя поиск его индекса? В (рабочем) примере ниже я хотел бы получить лучший способ реализовать removeContent (), то есть какой-то способ удалить элемент из списка без необходимости l oop. Я пытаюсь придерживаться базы R, если это вообще возможно.

Element <- setRefClass(
  Class ="Element",
  fields = list(
    m_name = "character",
    contentList = "list"
  ),
  methods = list(
    initialize = function(name = NULL) {
      "Element constructor, @param name, The name of the tag (optional)"
      if(!is.null(name)) {
        m_name <<- name
      }
    },

    addContent = function(content) {
      "Appends the child to the end of the content list. return the parent (the calling object)"
      idx <- length(contentList) + 1
      contentList[[idx]] <<- content
      return(.self)
    },

    findContentIndex = function(content) {
      "Find the position of the content in the contentList or -1 if not found"
      for (idx in seq_along(contentList)) {
        if(identical(content, contentList[[idx]])) {
          return(idx)
        }
      }
    -1
    },

    removeContent = function(content) {
      "Remove the specified content from this element"
      index <- findContentIndex(content)
      if ( index != -1){
        contentList <<- contentList[- index]
      } else {
        stop("There is no such content belonging to this Element")
      }
    }
  )
)

foo <- Element$new("foo")
foo$addContent(Element$new("Bar"))
baz <- Element$new("Baz")
foo$addContent(baz)
foo$removeContent(baz)
tryCatch(
  {
    foo$removeContent(baz)
  },
  error=function(cond) {
    print(paste("Expected this error, ", cond$message))
  }
)

1 Ответ

1 голос
/ 09 апреля 2020

Способ сделать это без использования явной индексации - использовать sapply(contentList, identical, content) для поиска подходящего объекта. Мы можем упростить все ваше определение класса, сохранив функциональность, например:

Element <- setRefClass(
  Class   = "Element",
  fields  = list(m_name = "character", contentList = "list"),
  methods = list(initialize    = function(name = NULL)
                                 {
                                   if (!is.null(name)) m_name <<- name
                                 },

                 addContent    = function(content) 
                                 {
                                   contentList <<- append(contentList, content)
                                 },

                 removeContent = function(content) 
                                 {
                                   idx <- sapply(contentList, identical, content)
                                   if (all(!idx)) stop("Content not found")
                                   contentList <<- contentList[!idx]
                                 })
  )

Теперь мы можем проверить его на ваших примерах:

foo <- Element$new("foo")
foo$addContent(Element$new("Bar"))
baz <- Element$new("Baz")
foo$addContent(baz)
foo
#> Reference class object of class "Element"
#> Field "m_name":
#> [1] "foo"
#> Field "contentList":
#> [[1]]
#> Reference class object of class "Element"
#> Field "m_name":
#> [1] "Bar"
#> Field "contentList":
#> list()
#> 
#> [[2]]
#> Reference class object of class "Element"
#> Field "m_name":
#> [1] "Baz"
#> Field "contentList":
#> list()
foo$removeContent(baz)
foo
#> Reference class object of class "Element"
#> Field "m_name":
#> [1] "foo"
#> Field "contentList":
#> [[1]]
#> Reference class object of class "Element"
#> Field "m_name":
#> [1] "Bar"
#> Field "contentList":
#> list()

и с вашим tryCatch:

tryCatch(
  {
    foo$removeContent(baz)
  },
  error=function(cond) {
    print(paste("Expected this error, ", cond$message))
  }
)
#> [1] "Expected this error,  Content not found"

Создано в 2020-04-08 пакетом Представить (v0.3.0)

...