使用 `assign()` 为列表项赋值
Assigning a value to a list item using `assign()`
先了解一下上下文...
我写了一个中缀函数,本质上取代了习语
x[[length(x) +1]] <- y
..或者简单地 x <- append(x, y)
向量。
这里是:
`%+=%` <- function(x, y) {
xcall <- substitute(x)
xobjname <- setdiff(all.names(xcall), c("[[", "[", ":", "$"))
# if the object doesn't exist, create it
if (!exists(xobjname, parent.frame(), mode = "list") &&
!exists(xobjname, parent.frame(), mode = "numeric") &&
!exists(xobjname, parent.frame(), mode = "character")) {
xobj <- subset(y, FALSE)
} else {
xobj <- eval(xcall, envir = parent.frame())
}
if (is.atomic(xobj)) {
if (!is.atomic(y)) {
stop('Cannot append object of mode ', dQuote(mode(y)),
' to atomic structure ', xobjname)
}
assign(xobjname, append(xobj, y), envir = parent.frame())
return(invisible())
}
if (is.list(xobj)) {
if (is.atomic(y)) {
xobj[[length(xobj) + 1]] <- y
} else {
for (i in seq_along(y)) {
xobj[[length(xobj) + 1]] <- y[[i]]
names(xobj)[length(xobj)] <- names(y[i])
}
}
assign(xobjname, xobj, envir = parent.frame())
return(invisible())
}
stop("Can't append to an object of mode ",
mode(eval(xcall, envir = parent.frame())))
}
它按预期与向量或列表一起工作,但其当前形式的限制是我无法将值附加到列表中的项目,例如:
a <- list(a = 1, b = 2)
a$b %+=% 3
到目前为止我还没有找到如何去做。我试过类似下面的方法,但没有效果:
assign("b", append(a$b, 3), envir = as.environment(a))
有什么想法吗?
建议不要使用赋值,而是:
`%+=%`<- function(x, value) eval.parent(substitute(x <- append(x, value)))
x <- 3
x %+=% 5
x
## [1] 3 5
L <- list(a = 1, b = 2)
L %+=% 3
## List of 3
## $ a: num 1
## $ b: num 2
## $ : num 3
L <- list(a = 1, b = 2)
L$a %+=% 4
str(L)
## List of 2
## $ a: num [1:2] 1 4
## $ b: num 2
或尝试 +<- 避免 eval
:
的语法
`+<-` <- append
# test
x <- 3
+x <- 1
x
## [1] 3 1
# test
L<- list(a = 1, b = 2)
+L <- 10
str(L)
## List of 3
## $ a: num 1
## $ b: num 2
## $ : num 10
# test
L <- list(a = 1, b = 2)
+L$a <- 10
str(L)
## List of 2
## $ a: num [1:2] 1 10
## $ b: num 2
或者试试这个类似于 +<-
的替换函数语法。
`append<-` <- append
x <- 3
append(x) <- 7
## [1] 3 7
... etc ...
先了解一下上下文...
我写了一个中缀函数,本质上取代了习语
x[[length(x) +1]] <- y
..或者简单地 x <- append(x, y)
向量。
这里是:
`%+=%` <- function(x, y) {
xcall <- substitute(x)
xobjname <- setdiff(all.names(xcall), c("[[", "[", ":", "$"))
# if the object doesn't exist, create it
if (!exists(xobjname, parent.frame(), mode = "list") &&
!exists(xobjname, parent.frame(), mode = "numeric") &&
!exists(xobjname, parent.frame(), mode = "character")) {
xobj <- subset(y, FALSE)
} else {
xobj <- eval(xcall, envir = parent.frame())
}
if (is.atomic(xobj)) {
if (!is.atomic(y)) {
stop('Cannot append object of mode ', dQuote(mode(y)),
' to atomic structure ', xobjname)
}
assign(xobjname, append(xobj, y), envir = parent.frame())
return(invisible())
}
if (is.list(xobj)) {
if (is.atomic(y)) {
xobj[[length(xobj) + 1]] <- y
} else {
for (i in seq_along(y)) {
xobj[[length(xobj) + 1]] <- y[[i]]
names(xobj)[length(xobj)] <- names(y[i])
}
}
assign(xobjname, xobj, envir = parent.frame())
return(invisible())
}
stop("Can't append to an object of mode ",
mode(eval(xcall, envir = parent.frame())))
}
它按预期与向量或列表一起工作,但其当前形式的限制是我无法将值附加到列表中的项目,例如:
a <- list(a = 1, b = 2)
a$b %+=% 3
到目前为止我还没有找到如何去做。我试过类似下面的方法,但没有效果:
assign("b", append(a$b, 3), envir = as.environment(a))
有什么想法吗?
建议不要使用赋值,而是:
`%+=%`<- function(x, value) eval.parent(substitute(x <- append(x, value)))
x <- 3
x %+=% 5
x
## [1] 3 5
L <- list(a = 1, b = 2)
L %+=% 3
## List of 3
## $ a: num 1
## $ b: num 2
## $ : num 3
L <- list(a = 1, b = 2)
L$a %+=% 4
str(L)
## List of 2
## $ a: num [1:2] 1 4
## $ b: num 2
或尝试 +<- 避免 eval
:
`+<-` <- append
# test
x <- 3
+x <- 1
x
## [1] 3 1
# test
L<- list(a = 1, b = 2)
+L <- 10
str(L)
## List of 3
## $ a: num 1
## $ b: num 2
## $ : num 10
# test
L <- list(a = 1, b = 2)
+L$a <- 10
str(L)
## List of 2
## $ a: num [1:2] 1 10
## $ b: num 2
或者试试这个类似于 +<-
的替换函数语法。
`append<-` <- append
x <- 3
append(x) <- 7
## [1] 3 7
... etc ...