create a sequence that replicates itself excluding the last element

127 Views Asked by At

Is there a way to create a sequence that replicates itself excluding the last element without a loop? Say we have a starting sequence 4:1 and the function fun that generates the rest of the sequence like:

> fun(4:1)
[1] 4 3 2 1 4 3 2 4 3 4
7

There are 7 best solutions below

1
danlooo On
fun <- function(x) {
  x |>
  length() |>
  seq() |>
  sapply(function(y) x[1:y]) |>
  rev() |>
  purrr::simplify()
}

fun(4:1)
#> [1] 4 3 2 1 4 3 2 4 3 4
0
B. Christian Kamgang On

One way to solve your problem:

v = 4:1
unlist(lapply(4:1, rep_len, x=rev(seq_along(v)))

[1] 4 3 2 1 4 3 2 4 3 4

if you prefer a custom function:

fun = function(x) {
  nx = rev(seq_along(x))
  unlist(lapply(x, rep_len, x=nx))
}

fun(v)
[1] 4 3 2 1 4 3 2 4 3 4
4
jay.sf On

Using sequence.

5L - sequence(4:1)
# [1] 4 3 2 1 4 3 2 4 3 4

As function:

f <- \(n) (n + 1) - sequence(n:1)
f(4)
# [1] 4 3 2 1 4 3 2 4 3 4

Or

f2 <- \(seq) seq[1] + 1 - sequence(seq)
f2(4:1)
# [1] 4 3 2 1 4 3 2 4 3 4

For sequences not ending with 1 maybe

f3 <- \(s) unlist(list(s, lapply(1:diff(range(s)) - 1, \(i) s[-((length(s) - i):length(s))])))
f3(5:3)
# [1] 5 4 3 5 4 5
1
Andre Wildberg On

Using matrix, also works with lower bounds > 1

fun <- function(x){lx <- length(x); m <- matrix(x, nrow=lx, ncol=lx) 
                   m[upper.tri(m, diag=T)[, lx:1]]}

fun(4:1)
 [1] 4 3 2 1 4 3 2 4 3 4

fun(5:2)
 [1] 5 4 3 2 5 4 3 5 4 5
0
Gregor Thomas On

We can use head() iteratively on the vector:

foo = function(x) {
  lapply(rev(seq_along(x)), head, x = x) |> unlist()
}

foo(6:2)
# [1] 6 5 4 3 2 6 5 4 3 6 5 4 6 5 6
foo(4:1)
# [1] 4 3 2 1 4 3 2 4 3 4
0
M.Viking On

Building on the sequence() answer by @jay.sf - However this only works on sequences ending in 1.

sequence(4:1, from=4, by=-1L)
#  [1] 4 3 2 1 4 3 2 4 3 4

fx <- function(x) {
  sequence(x, from=head(x, 1), by=-1L)
}
fx(4:1)
#  [1] 4 3 2 1 4 3 2 4 3 4
fx(5:3)
#  [1] 5 4 3 2 1 5 4 3 2 5 4 3 #wrong result

Edit: And my approach to making a matrix and taking the "upper left triangle" is the same as @AndreWildberg .. removing:

0
Maël On

Here's a sequence option that would work in any case:

rev_seq <- function(s) sequence(rev(seq(s)), s[1], -1)

outputs

rev_seq(5:3)
#[1] 5 4 3 5 4 5

rev_seq(4:1)
#[1] 4 3 2 1 4 3 2 4 3 4