我需要按如下方式生成数字序列:
1 1,2 1,2,3 ... 1,2,3 ...,N 2 2,3 2,3,4 ... 2,3,4,...,N ... ... n-1个 n-1个,正 Ñ
我来自其他编程语言,其中循环非常好。但是我理解R社区偏爱所谓的矢量化操作而不是循环(更有效率,虽然我没有阅读所有关于其原因的细节)。
所以,我想要做的第一件事就是循环。我写了这个代码,肯定能完成这项工作(R大师说3,2,1中的euhh ......)
n <- 30
accum <- list()
for (x in 1:n) {
for (y in x:n) {
accum[[paste(x,y)]] <- x:y
}
}
但这是丑陋的代码(我觉得效率不高)。
那么,对于我的问题,什么是聪明的R风格代码?
我当然没有掌握矢量化操作和应用族函数。但我最好的一点是:
n <- 30
accum <- lapply(1:n, FUN = function(x){lapply(x:n, FUN = seq, from = x)})
不知道这是不是很好的R风格编码,但几乎完成了工作。此解决方案的问题在于它生成一个包含n
元素的列表,这些元素也是列表并包含序列。但我想要的是一个包含465个元素的列表(在n = 30的情况下),因此每个序列只有一个元素,而没有该解决方案产生的所有列表嵌套。
我真的很感激R世界中聪明而优雅的解决方案。
答案 0 :(得分:1)
获取单个载体:
n <- 4
u <- sequence(n:1)
(v <- sequence(u) + rep(1:n, rev(cumsum(1:n))) - 1)
# [1] 1 1 2 1 2 3 1 2 3 4 2 2 3 2 3 4 3 3 4 4
和矢量列表:
split(v, rep(cumsum(u), u))
或与您的解决方案非常相似的东西:
Reduce('c', lapply(1:n, function(x) lapply(x:n, seq, from = x)))
答案 1 :(得分:1)
你的第二个解决方案是好的。您所要做的只是unlist
一层。
unlist(lapply(1:n, FUN = function(x) lapply(x:n, FUN = seq, from = x)), rec=FALSE)
这里有你的伪装名单monad。为了更清楚,请考虑以下内容,这是等效的
mapcat <- function(x,f,...) unlist(lapply(x,f,...),rec=FALSE)
mapcat(1:n,function(a) mapcat(a:n, function(b) list(seq(a,b))))
此处mapcat
是绑定操作,list
是单位/返回。
在具有列表monad的do-notation的语言中,这可以写成,例如在Haskell中,作为
do
a <- [1..n]
b <- [a..n]
return([a..b])
我不知道任何带有这种糖的R包,但使用foreach
库,我们可以更接近
library(foreach)
foreach(a=1:n, .combine='c') %:% foreach(b=a:n) %do% seq(a,b)