Search code examples
rvector

Is there an R function to repeat a value for the length of value, then skip ahead and then repeat the next value that is value+1 index ahead


I have a string of numbers, such like: string <- c(4, 3, 4, 4, 3, 4, 3, 3, 2, 1, 1, 1, 2, 3, 2, 1, 1, 2, 1, 2, 1, 3, 1) and I need to be able to replace the values based on their position, so that the first value is repeated four times, and then the replaced values are skipped and the next value is used (e.g. 3).

I have tried writing a function to do this, but cannot get it in a form so that it overwrites the existing data and then skips ahead. In my head, I think I need to update the data input into the function based on the function output

I expect an output of c(4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 1, 1, 2, 2, 2, 2, 1, 2, 2, 3, 3, 3, 3), so the first value of 4 is repeated four times, then the fifth value of 3 is repeating three times, then the eighth values of 3 is repeated 3 times etc.

I have so far been able to repeat each values the correct length, but I need to then filter out the unnecessary values, ideally they would never be included.

string <- c(4, 3, 4, 4, 3, 4, 3, 3, 2, 1, 1, 1, 2, 3, 2, 1, 1, 2, 1, 2, 1, 1, 1)
  
  temp <- function(i) {  
    
  data.frame(x = rep(string[i], string[i]))

  }
  
  do.call("rbind", lapply(seq(length(string)), temp))

Solution

  • This seems to be a bit tricky to do in a vectorized way because you kind of need to keep track of state, But you could use Reduce

    
    filler <- function(x, y) {
      x$rem <- x$rem-1
      if(x$rem<1) {
        x$rem = x$val = y
      }
      x
    }
    
    Reduce(filler, string, init = list(rem=0), accumulate = TRUE) |> 
      tail(-1) |> 
      sapply(`[[`, "val")
    

    or just a loop

    output <- string
    i <- 1
    while(i < length(string)) {
      fill <- string[i]
      output[i:(i+fill-1)] <- fill
      i <- i + fill
    }
    output