# 循环递增时避免for循环

In R, I try systematically to avoid "for" loops and use `lapply()` family instead.
But how to do so when an iteration contains an increment step ?

For example : is it possible to obtain the same result as below with a `lapply` approach ?

``````a <- c()
b <- c()
for (i in 1:10){
a <- c(a, i)
b <- c(b, (paste(a, collapse = "-")))
}
data.frame(a, b)

> data.frame(a, b)
>     a                    b
> 1   1                    1
> 2   2                  1-2
> 3   3                1-2-3
> 4   4              1-2-3-4
> 5   5            1-2-3-4-5
> 6   6          1-2-3-4-5-6
> 7   7        1-2-3-4-5-6-7
> 8   8      1-2-3-4-5-6-7-8
> 9   9    1-2-3-4-5-6-7-8-9
> 10 10 1-2-3-4-5-6-7-8-9-10
``````

• Wolf 回复

Another way is to use `Reduce` with `accumulate = TRUE`, i.e.

``````df\$new <- do.call(rbind, Reduce(paste, split(df, seq(nrow(df))), accumulate = TRUE))
``````

这使，

``````    a                  new
1   1                    1
2   2                  1 2
3   3                1 2 3
4   4              1 2 3 4
5   5            1 2 3 4 5
6   6          1 2 3 4 5 6
7   7        1 2 3 4 5 6 7
8   8      1 2 3 4 5 6 7 8
9   9    1 2 3 4 5 6 7 8 9
10 10 1 2 3 4 5 6 7 8 9 10
``````
• wsed 回复

Another way of using `Reduce`, different to the approach by @Sotos

``````df\$b <- Reduce(function(...) paste(...,sep = "-"), df\$a, accumulate = T)
``````

这样

``````> df
a                    b
1   1                    1
2   2                  1-2
3   3                1-2-3
4   4              1-2-3-4
5   5            1-2-3-4-5
6   6          1-2-3-4-5-6
7   7        1-2-3-4-5-6-7
8   8      1-2-3-4-5-6-7-8
9   9    1-2-3-4-5-6-7-8-9
10 10 1-2-3-4-5-6-7-8-9-10
``````
• qodio 回复

You can use `sapply` (`lapply` would work too but it returns a list) and iterate over every value of `a` in `df` and create a sequence and `paste` the value together.

``````df <- data.frame(a = 1:10)
df\$b <- sapply(df\$a, function(x) paste(seq(x), collapse = "-"))
df

#    a                    b
#1   1                    1
#2   2                  1-2
#3   3                1-2-3
#4   4              1-2-3-4
#5   5            1-2-3-4-5
#6   6          1-2-3-4-5-6
#7   7        1-2-3-4-5-6-7
#8   8      1-2-3-4-5-6-7-8
#9   9    1-2-3-4-5-6-7-8-9
#10 10 1-2-3-4-5-6-7-8-9-10
``````

If there could be non-numerical values in data on which we can not use `seq` like

``````df <- data.frame(a =letters[1:10])
``````

在那种情况下，我们可以使用

``````df\$b <- sapply(seq_along(df\$a), function(x) paste(df\$a[seq_len(x)], collapse = "-"))
df

#   a                   b
#1  a                   a
#2  b                 a-b
#3  c               a-b-c
#4  d             a-b-c-d
#5  e           a-b-c-d-e
#6  f         a-b-c-d-e-f
#7  g       a-b-c-d-e-f-g
#8  h     a-b-c-d-e-f-g-h
#9  i   a-b-c-d-e-f-g-h-i
#10 j a-b-c-d-e-f-g-h-i-j
``````
• 行文华 回复

For the sake of completeness, there is also the `accumulate()` function from the `purrr` package.

So, building on the answers of Sotos and ThomasIsCoding:

``````df <- data.frame(a = 1:10)
df\$b <- purrr::accumulate(df\$a, paste, sep = "-")
df
``````
``````    a                    b
1   1                    1
2   2                  1-2
3   3                1-2-3
4   4              1-2-3-4
5   5            1-2-3-4-5
6   6          1-2-3-4-5-6
7   7        1-2-3-4-5-6-7
8   8      1-2-3-4-5-6-7-8
9   9    1-2-3-4-5-6-7-8-9
10 10 1-2-3-4-5-6-7-8-9-10
``````

The difference to `Reduce()` is

• that `accumulate()` is a function verb on its own (no additional parameter `accumulate = TRUE` required)
• and that additional arguments like `sep = "-"` can be passed on to the mapped function which may help to avoid the creation of an anonymous function.