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
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
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
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
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
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: