2012-05-19 18 views
5

En una pregunta aquí en SO (LINK) un cartel hizo una pregunta y respondí que funciona pero hay una parte que me molesta, creando un list de un vector para pasar como una lista de índices. Así que les digo que tengo este vector:Haz una lista de vectores de igual longitud

n <- 1:10 
#> n 
# [1] 1 2 3 4 5 6 7 8 9 10 

Digamos que quiero dividirlo en una lista de vectores y cada vector es de longitud 3. ¿Cuál es la mejor (menor cantidad de código & o más rápida) a lograr esto? Queremos descartar el artículo 10 ya que hay un resto de 1 (10 %% 3) de 10/3 (length(n) - 10 %% 3).

Este es el resultado deseado

list(1:3, 4:6, 7:9) 

Esto nos dará los índices de los que no pueden hacer que un grupo de tres:

(length(n) + 1 - 10 %% 3):length(n) 

EDITAR

He aquí una enfoque interesante publicado por Wojciech Sobala en el other thread al que está vinculado (les pedí que respondieran aquí y si lo hacen eliminaré t su edición)

n <- 100 
l <- 3 
n2 <- n - (n %% l) 
split(1:n2, rep(1:n2, each=l, length=n2)) 

En función:

indices <- function(n, l){ 
    if(n > l) stop("n needs to be smaller than or equal to l") 
    n2 <- n - (n %% l) 
    cat("numbers", (n + 1 - n %% l):n, "did not make an index of length", l) 
    split(1:n2, rep(1:n2, each=l, length=n2)) 
} 
+0

Todos los grandes respuestas, pero creo que X , Él es el código más breve. Gracias, eso me estaba molestando. Todos los enfoques son mucho mejores que lo que estaba haciendo. –

Respuesta

5

No estoy seguro si esto hace el trabajo?

x = function(x, n){ 
    if(n > x) stop("n needs to be smaller than or equal to x") 
    output = matrix(1:(x-x%%n), ncol=(x-x%%n)/n, byrow=FALSE) 
    output 
} 

Editar: cambia la salida a una lista

x = function(x, n){ 
    if(n > x) stop("n needs to be smaller than or equal to x") 
    output = matrix(1:(x-x%%n), ncol=(x-x%%n)/n, byrow=TRUE) 
    split(output, 1:nrow(output)) 
} 

Example: 
x(10, 3) 
$`1` 
[1] 1 2 3 

$`2` 
[1] 4 5 6 

$`3` 
[1] 7 8 9 
+0

Muy simple. +1 –

+0

@ tyler-rinker Aunque no estoy seguro de si es rápido ... – Alex

+0

Aunque no es una lista, no funcionará en la pregunta del póster a menos que ajuste el 'output' con' data.frame' –

4
xx <- 1:10 
xxr <- rle(0:(length(1:10)-1) %/% 3) # creates an rle object 
fac3 <- rep(xxr$values[xxr$lengths == 3], each=3) #selects the one of length 3 
            # and recreates the shortened grouping vector 
tapply(xx[ 1:length(fac3)],   # a shortened original vector 
         fac3, list) # split into little lists 
$`0`        # Hope you don't mind having names on your list 
[1] 1 2 3 

$`1` 
[1] 4 5 6 

$`2` 
[1] 7 8 9 
+0

No edité tu respuesta, solo puse mi edición en el lugar equivocado, disculpas. +1 –

3

No es la más corta, pero aquí hay un poco de la versión recursiva:

wrap <- function(n,x,lx,y) { 
    if (lx < n) return (y) 
    z <- x[-(1:n)] 
    wrap(n, z, length(z), c(y, list(x[1:n]))) 
} 

wrapit <- function(x,n) { 
    wrap(n,x,length(x),list()) 
} 

> wrapit(1:10,3) 
[[1]] 
[1] 1 2 3 

[[2]] 
[1] 4 5 6 

[[3]] 
[1] 7 8 9 
+0

Wow, este me duele los fideos. +1 Ni siquiera estoy seguro de cómo funciona (aunque los índices están en orden inverso) –

+1

Para comprender las funciones recursivas, a veces puede ser útil seguir la cadena de llamadas de función con papel y lápiz. O ponga un par de declaraciones de impresión allí para ver cómo la lista crece y el vector se reduce. –

Cuestiones relacionadas