我正在尝试设置一些感觉应该很简单的东西,但我无法找到解决方案。我写了一个我的代码的精简版本,试图在整个过程中解释它。
基本上,我想每一代创建一组“孩子”。然后,将每年的年龄加1,并在年龄> 1时删除列表条目。 3.代码几乎可以工作 - 我认为问题与调用fl的长度然后从列表中删除行有关,但我不确定。如果结果正常,最终结果(fl)不应该有大于3的条目。
代码:
#NUMBER OF PARENTS TO START WITH
parents <- 10
#NUMBER OF GENERATIONS TO RUN
generations <- 5
#NUMBER OF CHILDREN TO CREATE EACH GENERATION
children <- 5
#AGE TO KILL
death <- 3
pl <- list()
cl <- list()
fl <- list()
kl <- list()
#CREATE PARENTS
for (i2 in 1:parents) {
pl[[i2]] <- 0
}
fl <- pl
#START GEN LOOP
i3 <- 0
while (i3 < generations) {
i3 <- i3 + 1
#CREATE CHILDREN
for (i5 in 1:children) {
cl[[i5]] <- 0
}
#ADD CHILDREN TO FINAL LIST
fl <- c(fl, cl)
#ADD 1 TO AGE
for (i6 in 1:length(fl)) {
fl[[i6]] <- fl[[i6]] + 1
}
###PROBLEM###
#KILL BASED ON AGE
i4 <- 0
while (i4 < length(fl)) {
i4 <- i4 + 1
if (fl[[i4]] > death) {
#ADD TO KILL LIST FOR DEBUGGING
kl <- c(kl, fl[[i4]])
#REMOVE FROM fl
fl <- fl[-c(i4), drop=FALSE]
}
}
#CLOSE GEN LOOP
}
fl
谢谢!
答案 0 :(得分:2)
通常在使用R时,您希望尽可能避免循环。它很慢,你可以使用它来避免它。我认为你的原始代码不起作用,因为你正在循环,你正在删除一个元素,然后索引会改变,然后在下一次迭代中你最终删除了错误的元素。我改变了你的代码,看看你的想法:
#NUMBER OF PARENTS TO START WITH
parents <- 10
#NUMBER OF GENERATIONS TO RUN
generations <- 5
#NUMBER OF CHILDREN TO CREATE EACH GENERATION
children <- 5
#AGE TO KILL
death <- 3
pl <- list()
cl <- list()
fl <- list()
kl <- list()
#CREATE PARENTS
# for (i2 in 1:parents) {
# pl[[i2]] <- 0
# }
fl <- pl <- as.list(rep(0, parents))
# fl <- pl
#START GEN LOOP
i3 <- 0
while (i3 < generations) {
i3 <- i3 + 1
#CREATE CHILDREN
# for (i5 in 1:children) {
# cl[[i5]] <- 0
# }
cl <- as.list(rep(0, children))
#ADD CHILDREN TO FINAL LIST
fl <- c(fl, cl)
#ADD 1 TO AGE
# for (i6 in 1:length(fl)) {
# fl[[i6]] <- fl[[i6]] + 1
# }
fl <- lapply(fl, function(x) x+1)
###PROBLEM###
#KILL BASED ON AGE
# i4 <- 0
# while (i4 < length(fl)) {
# i4 <- i4 + 1
# if (fl[[i4]] > death) {
#
# #ADD TO KILL LIST FOR DEBUGGING
# kl <- c(kl, fl[[i4]])
#
# #REMOVE FROM fl
# fl <- fl[-c(i4), drop=FALSE]
# }
# }
fl <- fl[fl <= death]
#CLOSE GEN LOOP
}
fl
lapply
是你的朋友
答案 1 :(得分:1)
从列表中删除元素时,不会相应地调整i4
。试试这个:
###FIXED###
#KILL BASED ON AGE
i4 <- 0
while (i4 < length(fl)) {
i4 <- i4 + 1
if (fl[[i4]] > death) {
#ADD TO KILL LIST FOR DEBUGGING
kl <- c(kl, fl[[i4]])
#REMOVE FROM fl
fl <- fl[-c(i4), drop=FALSE]
i4 <- i4 - 1 # <------ added this line
}
}
此外,您的代码相当不标准(有点难以阅读)。这不是代码审核,但我至少建议使用for
而不是while
...我认为您的典型R用户会更舒服。我不确定lapply
实际上是正确的解决方案;它失去了一些循环的字面共振。但我会高度建议编写函数而不仅仅是一个循环墙。然后你可以写一些像
life <- function(n_parents, n_children, death_age, n_generations) {
fl <- as.list(rep(0, n_parents))
for (i in 1:n_generations) {
fl <- spawn_children(fl, n_children)
fl <- lapply(fl, `+`, 1) # increment ages by 1
fl <- kill_old_people(fl, death_age)
}
fl
}
life(
n_parents = 10,
n_children = 5,
death_age = 3,
n_generations = 5
)