Home > Net >  Split a vector into non-overlapping sub-list with increasing length
Split a vector into non-overlapping sub-list with increasing length

Time:08-05

Let's say I have this vector:

letters[1:7]
[1] "a" "b" "c" "d" "e" "f" "g"

I would like to split it into a non-overlapping list with increasing length of 1, and keep what is left behind (e.g. sub-list 4 should have 4 elements, but there's only one left, and I'd like to keep that one), like the following:

[[1]]
[1] "a"

[[2]]
[1] "b" "c"

[[3]]
[1] "d" "e" "f"

[[4]]
[1] "g"

Please do let me know any direction to solve this, thank you!

CodePudding user response:

Example vector:

x <- letters[1:7]

Solution:

n <- ceiling(0.5 * sqrt(1   8 * length(x)) - 0.5)
split(x, rep(1:n, 1:n)[1:length(x)])
#$`1`
#[1] "a"
#
#$`2`
#[1] "b" "c"
#
#$`3`
#[1] "d" "e" "f"
#
#$`4`
#[1] "g"

CodePudding user response:

Something quick'n dirty

splitter = function(x) {
  n = length(x)
  i = 1
  while ( i * (i   1L) / 2L < (n-i) ) i = i   1
  out = rep(i 1, n)
  out[1:(i * (i   1L) / 2L)] = rep(1:i, 1:i)
  unname(split(x, out))
}

splitter(x)

[[1]]
[1] "a"

[[2]]
[1] "b" "c"

[[3]]
[1] "d" "e" "f"

[[4]]
[1] "g"

CodePudding user response:

x <- letters[1:7]
splt <- rep(seq(length(x)), seq(length(x)))[seq(length(x))]

split(x, splt)
#> $`1`
#> [1] "a"
#> 
#> $`2`
#> [1] "b" "c"
#> 
#> $`3`
#> [1] "d" "e" "f"
#> 
#> $`4`
#> [1] "g"

Created on 2022-08-04 by the reprex package (v2.0.1)

  • Related