R 中用于分解多行分配的 LHS 的语法
Syntax in R for breaking up LHS of assignment over multiple lines
R 中将赋值的 LHS 拆分为多行的语法是什么?在其他编程语言中你可以做到。
这个的一个用例(请不要让这个例子分散一般语法问题的注意力)是因为(我相信)R 不支持引用循环占位符变量,所以当使用非常for 循环中的深层嵌套数据结构(如列表数据帧的递归列表)有时您可能会有很长的赋值 LHS,例如
results$cases[[i]]$samples[[j]]$portions[[k]]$analytes[[l]]$column <- x
我知道,您可能会说为什么不使用嵌套 lapplys 或其他东西,但那是一个单独的讨论。
我尝试将 LHS 括在括号中,您得到了
Error: could not find function "(<-"
您可以在不属于名称的任意 2 个字符之间放置一个换行符,并且在换行符之前不会留下语法上完整的表达式(以便解析器知道要查找更多)。 None 看起来不错,但基本上在任何 [[
或 $
之后或 ]]
之前,您都可以换行。例如:
results$
cases[[i]]$
samples[[j]]$
portions[[k]]$
analytes[[l]]$
column <- x
或者走极端,放入每个语法上有效的换行符(不引入括号,这会让你做更多):
results$
cases[[
i
]]$
samples[[
j
]]$
portions[[
k
]]$
analytes[[
l
]]$
column <-
x
有了圆括号,我们失去了 “不留下句法上完整的表达式” 规则,因为表达式在圆括号闭合之前不会完整。您可以在名称(对象或函数名称)中间以外的任何位置添加分隔符。对于这个例子,我不会为嵌套缩进烦恼。
(
results
$
cases
[[
i
]]
$
samples
[[
j
]]
$
portions
[[
k
]]
$
analytes
[[
l
]]
$
column
<-
x
)
如果你想引起对正在分配的 x
的注意,你也可以使用正确的分配。
x -> results$cases[[i]]$samples[[j]]$
portions[[k]]$analytes[[l]]$column
顺便提一下:元素运算符 [[
支持列表的递归索引,如“递归 (list-like) 对象”下的 ?Extract
中所述。
需要注意的是,您必须为每个递归级别提供一个整数或字符索引。不支持混合,因此如果任何子列表没有 names
属性,您必须按整数索引。
x <- list(a = list(a1 = 1, a2 = 2), b = list(b1 = 3, b2 = 4))
x[[c(1L, 1L)]]
## [1] 1
x[[c("a", "a2")]]
## [1] 2
x[[c(2L, 1L)]] <- 30
x[[c(2L, 1L)]]
## [1] 30
x[[c("b", "b2")]] <- 40
x[[c("b", "b2")]]
## [1] 40
x[[list(1L, "a1")]]
## Error in x[[list(1L, "a1")]] : invalid subscript type 'list'
您始终可以实现支持混合类型索引的访问器:
rget <- function(x, i) {
if (is.list(i)) {
for (j in i) {
x <- x[[j]]
}
x
} else {
x[[i]]
}
}
`rset<-` <- function(x, i, value) {
if (is.list(i)) {
y <- x
n <- length(i)
ii <- integer(n)
for (k in seq_len(n)) {
j <- i[[k]]
ii[k] <- if (is.character(j)) match(j, names(y)) else j
y <- y[[j]]
}
x[[ii]] <- value
} else {
x[[i]] <- value
}
x
}
然后:
rget(x, list(1L, "a1"))
## [1] 1
rset(x, list(1L, "a1")) <- 10
rget(x, list(1L, "a1"))
## [1] 10
您只需要接受 for
循环的开销。
R 中将赋值的 LHS 拆分为多行的语法是什么?在其他编程语言中你可以做到。
这个的一个用例(请不要让这个例子分散一般语法问题的注意力)是因为(我相信)R 不支持引用循环占位符变量,所以当使用非常for 循环中的深层嵌套数据结构(如列表数据帧的递归列表)有时您可能会有很长的赋值 LHS,例如
results$cases[[i]]$samples[[j]]$portions[[k]]$analytes[[l]]$column <- x
我知道,您可能会说为什么不使用嵌套 lapplys 或其他东西,但那是一个单独的讨论。
我尝试将 LHS 括在括号中,您得到了
Error: could not find function "(<-"
您可以在不属于名称的任意 2 个字符之间放置一个换行符,并且在换行符之前不会留下语法上完整的表达式(以便解析器知道要查找更多)。 None 看起来不错,但基本上在任何 [[
或 $
之后或 ]]
之前,您都可以换行。例如:
results$
cases[[i]]$
samples[[j]]$
portions[[k]]$
analytes[[l]]$
column <- x
或者走极端,放入每个语法上有效的换行符(不引入括号,这会让你做更多):
results$
cases[[
i
]]$
samples[[
j
]]$
portions[[
k
]]$
analytes[[
l
]]$
column <-
x
有了圆括号,我们失去了 “不留下句法上完整的表达式” 规则,因为表达式在圆括号闭合之前不会完整。您可以在名称(对象或函数名称)中间以外的任何位置添加分隔符。对于这个例子,我不会为嵌套缩进烦恼。
(
results
$
cases
[[
i
]]
$
samples
[[
j
]]
$
portions
[[
k
]]
$
analytes
[[
l
]]
$
column
<-
x
)
如果你想引起对正在分配的 x
的注意,你也可以使用正确的分配。
x -> results$cases[[i]]$samples[[j]]$
portions[[k]]$analytes[[l]]$column
顺便提一下:元素运算符 [[
支持列表的递归索引,如“递归 (list-like) 对象”下的 ?Extract
中所述。
需要注意的是,您必须为每个递归级别提供一个整数或字符索引。不支持混合,因此如果任何子列表没有 names
属性,您必须按整数索引。
x <- list(a = list(a1 = 1, a2 = 2), b = list(b1 = 3, b2 = 4))
x[[c(1L, 1L)]]
## [1] 1
x[[c("a", "a2")]]
## [1] 2
x[[c(2L, 1L)]] <- 30
x[[c(2L, 1L)]]
## [1] 30
x[[c("b", "b2")]] <- 40
x[[c("b", "b2")]]
## [1] 40
x[[list(1L, "a1")]]
## Error in x[[list(1L, "a1")]] : invalid subscript type 'list'
您始终可以实现支持混合类型索引的访问器:
rget <- function(x, i) {
if (is.list(i)) {
for (j in i) {
x <- x[[j]]
}
x
} else {
x[[i]]
}
}
`rset<-` <- function(x, i, value) {
if (is.list(i)) {
y <- x
n <- length(i)
ii <- integer(n)
for (k in seq_len(n)) {
j <- i[[k]]
ii[k] <- if (is.character(j)) match(j, names(y)) else j
y <- y[[j]]
}
x[[ii]] <- value
} else {
x[[i]] <- value
}
x
}
然后:
rget(x, list(1L, "a1"))
## [1] 1
rset(x, list(1L, "a1")) <- 10
rget(x, list(1L, "a1"))
## [1] 10
您只需要接受 for
循环的开销。