Добавьте объект к списку в R в амортизируемое постоянное время, O (1)?

Если у меня есть некоторый список R mylist, можно добавить объект obj к нему как так:

mylist[[length(mylist)+1]] <- obj

Но конечно существует некоторый более компактный путь. Когда я был новым в R, я пытался писать lappend() как так:

lappend <- function(lst, obj) {
    lst[[length(lst)+1]] <- obj
    return(lst)
}

но конечно который не работает из-за семантики вызова по имени R (lst эффективно копируется на вызов, так изменения в lst не видимы вне объема lappend(). Я знаю, что можно сделать взламывание среды в функции R, чтобы достигнуть вне объема функции и видоизменить среду вызова, но это походит на большой молоток, чтобы записать, что простое добавляет функцию.

Кто-либо может предложить более красивый способ сделать это? Бонусные очки, если это работает и на векторы и на списки.

235
задан smci 28 April 2016 в 08:22
поделиться

4 ответа

Если это список строк, просто используйте функцию c() :

R> LL <- list(a="tom", b="dick")
R> c(LL, c="harry")
$a
[1] "tom"

$b
[1] "dick"

$c
[1] "harry"

R> class(LL)
[1] "list"
R> 

Это работает и для векторов, так что получу ли я бонусные очки?

Edit (2015-Feb-01): Этому посту исполняется пять лет. Некоторые добрые читатели продолжают повторять любые недостатки в нем, так что непременно ознакомьтесь также с некоторыми комментариями ниже. Одно предложение по поводу list типов:

newlist <- list(oldlist, list(someobj))

В целом, типы R могут затруднить создание одной и только одной идиомы для всех типов и применений.

252
ответ дан 23 November 2019 в 03:28
поделиться

Это простой способ добавить элементы в список R:

# create an empty list:
small_list = list()

# now put some objects in it:
small_list$k1 = "v1"
small_list$k2 = "v2"
small_list$k3 = 1:10

# retrieve them the same way:
small_list$k1
# returns "v1"

# "index" notation works as well:
small_list["k2"]

Или программно:

kx = paste(LETTERS[1:5], 1:5, sep="")
vx = runif(5)
lx = list()
cn = 1

for (itm in kx) { lx[itm] = vx[cn]; cn = cn + 1 }

print(length(lx))
# returns 5
2
ответ дан 23 November 2019 в 03:28
поделиться

Если вы передадите переменную списка в виде строки в кавычках, вы сможете получить доступ к ней из функции, например:

push <- function(l, x) {
  assign(l, append(eval(as.name(l)), x), envir=parent.frame())
}

так:

> a <- list(1,2)
> a
[[1]]
[1] 1

[[2]]
[1] 2

> push("a", 3)
> a
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

> 

или за дополнительную плату:

> v <- vector()
> push("v", 1)
> v
[1] 1
> push("v", 2)
> v
[1] 1 2
> 
5
ответ дан 23 November 2019 в 03:28
поделиться

Вы хотите что-то вроде этого?

> push <- function(l, x) {
   lst <- get(l, parent.frame())
   lst[length(lst)+1] <- x
   assign(l, lst, envir=parent.frame())
 }
> a <- list(1,2)
> push('a', 6)
> a
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 6

Это не очень вежливая функция (присваивание parent.frame() является довольно грубым), но IIUYC это то, что вы просите.

6
ответ дан 23 November 2019 в 03:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: