Sequence of Number, through Iteration

Viewed 98

I have the following vector of indices

V_ind = cumsum(c(10,9,8,7,6,5,4,3,2,1))
[1] 10 19 27 34 40 45 49 52 54 55

And I created the following FOR LOOP

k=1

for(ind in V_ind){
 if(ind<=10){
  print("ok")
 }else{
  print(c(V_ind[1:k]))
  k = k + 1
 }

}

Which gives as a result

[1] "ok"
[1] 10
[1] 10 19
[1] 10 19 27
[1] 10 19 27 34
[1] 10 19 27 34 40
[1] 10 19 27 34 40 45
[1] 10 19 27 34 40 45 49
[1] 10 19 27 34 40 45 49 52
[1] 10 19 27 34 40 45 49 52 54

However, what I try to acheive is the following result

[1] "ok"
[1] 10
[1]  9 10 19
[1]  8  9 10 18 19 27
[1]  7  8  9 10 17 18 19 26 27 34
[1]  6  7  8  9 10 16 17 18 19 25 26 27 33 34 40
[1]  5  6  7  8  9 10 15 16 17 18 19 24 25 26 27 32 33 34 39 40 45
[1]  4  5  6  7  8  9 10 14 15 16 17 18 19 23 24 25 26 27 31 32 33 34 38 39 40 44 45 49
[1]  3  4  5  6  7  8  9 10 13 14 15 16 17 18 19 22 23 24 25 26 27 30 31 32 33 34 37 38 39 40 43 44 45 48 49 52
[1]  2  3  4  5  6  7  8  9 10 12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 29 30 31 32 33 34 36 37 38 39 40 42 43 44 45 47 48 49 51 52 54

This result goes as follows:

  1. In the first iteration, we just print OK

  2. In the second iteration, we extract the first element of the vector V_ind,

  3. In the third iteration, we extract the first and second element of the vector V_ind together with the first element of the vector V_ind minus 1 that is the number 9.

  4. In the fourth iteration, we extract the first, second and third element of the vector V_ind, together with the first element minus 1, i.e. 9, first element minus 2, i.e 8, and second element minus 1,i.e.18.

  5. In the fifth iteration, we extract the first, second, third and fourth element of the vector V_ind together with the first element minus 1, 2, 3 respectively, i.e 7,8,9, also the second element minus 1 and 2, i.e 17,18, and the third element minus 1, i.e 26.

And this procedure goes until the end of the FOR LOOP. Is this even possible to be done in R, in a generic way?

3 Answers

One option using purrr could be:

map(.x = accumulate(V_ind, c),
    ~ map2(.x,
           rev(seq_along(.x) - 1),
           function(y, z) seq(y - z, y, 1)) %>%
        reduce(c))

[[1]]
[1] 10

[[2]]
[1]  9 10 19

[[3]]
[1]  8  9 10 18 19 27

[[4]]
 [1]  7  8  9 10 17 18 19 26 27 34

[[5]]
 [1]  6  7  8  9 10 16 17 18 19 25 26 27 33 34 40

[[6]]
 [1]  5  6  7  8  9 10 15 16 17 18 19 24 25 26 27 32 33 34 39 40 45

[[7]]
 [1]  4  5  6  7  8  9 10 14 15 16 17 18 19 23 24 25 26 27 31 32 33 34 38 39 40 44 45 49

[[8]]
 [1]  3  4  5  6  7  8  9 10 13 14 15 16 17 18 19 22 23 24 25 26 27 30 31 32 33 34 37 38 39 40 43 44 45 48 49 52

[[9]]
 [1]  2  3  4  5  6  7  8  9 10 12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 29 30 31 32 33 34 36 37 38 39 40 42 43 44 45 47 48
[42] 49 51 52 54

[[10]]
 [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
[42] 42 43 44 45 46 47 48 49 50 51 52 53 54 55

And if it's important, you can simply add the "OK" iteration retrospesctively:

append("OK",
       map(.x = accumulate(V_ind, c),
           ~ map2(.x,
                  rev(seq_along(.x) - 1),
                  function(y, z) seq(y - z, y, 1)) %>%
               reduce(c)))

Likewise, if you need to leave out the last number from the original vector:

append("OK",
       map(.x = accumulate(head(V_ind, -1), c),
           ~ map2(.x,
                  rev(seq_along(.x) - 1),
                  function(y, z) seq(y - z, y, 1)) %>%
               reduce(c)))
for (i in seq_along(V_ind)) {
  if (i == 1) {
    print("ok")
  } else if (i == 2) {
    print(V_ind[1]) 
  } else {
    out_vector <- V_ind[seq(i - 1)]
    max_minus <- i - 2
    
    minus_indices <- rep(seq(max_minus), rev(seq(max_minus)) + 1)
    minus_vector <- c()
    for (j in rev(seq(max_minus))) {
      minus_vector <- c(minus_vector, rev(seq(0, j)))
    }
    
    out_vector <- numeric(length(minus_vector))
    for (k in seq_along(out_vector)) {
      out_vector[k] <- V_ind[minus_indices[k]] - minus_vector[k]
    }
    print(c(out_vector, V_ind[i - 1]))
  }
}

[1] "ok"
[1] 10
[1]  9 10 19
[1]  8  9 10 18 19 27
 [1]  7  8  9 10 17 18 19 26 27 34
 [1]  6  7  8  9 10 16 17 18 19 25 26 27 33 34 40
 [1]  5  6  7  8  9 10 15 16 17 18 19 24 25 26 27 32 33 34 39 40 45
 [1]  4  5  6  7  8  9 10 14 15 16 17 18 19 23 24 25 26 27 31 32 33 34 38 39 40 44 45 49
 [1]  3  4  5  6  7  8  9 10 13 14 15 16 17 18 19 22 23 24 25 26 27 30 31 32 33 34 37 38 39 40 43 44 45 48 49 52
 [1]  2  3  4  5  6  7  8  9 10 12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 29 30 31 32 33 34 36 37 38 39 40 42 43 44 45 47 48 49
[43] 51 52 54

You could define the indices at which to subtract, and how much to subtract, explicitly. (+1 added to seq for subtracting 0). Then you just have to append the last item (V_ind[i -1]) where no subtraction is performed to the vector

Another option where sequence plays the key role

lapply(seq_along(x), function(n){
  x[rep(1:n, n:1)] - rev(sequence(1:n) - 1)
})

# [[1]]
# [1] 10
# 
# [[2]]
# [1]  9 10 19
# 
# [[3]]
# [1]  8  9 10 18 19 27
# 
# [[4]]
# [1]  7  8  9 10 17 18 19 26 27 34

Where x is a subset of your vector:

x = cumsum(10:7)

If desired, just c "ok" to the above.

Related