2012-05-19 3 views
5

Dans une question ici sur SO (LINK) une affiche a posé une question et j'ai donné une réponse qui fonctionne mais il y a une partie qui me dérange, créant un list à partir d'un vecteur pour passer en liste d'indices. Donc les dire que j'ai ce vecteur:Faire une liste de vecteurs de longueur égale

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

Disons que je veux le casser dans une liste de vecteurs et chaque vecteur est de longueur 3. Quelle est la meilleure (la plus courte quantité de code & ou plus rapide) pour accomplir ceci? Nous voulons jeter l'article 10 car il y a un reste de 1 (10 %% 3) de 10/3 (length(n) - 10 %% 3).

Ceci est le résultat souhaité

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

Cela nous donnera les indices de ceux qui ne peuvent pas faire un groupe de trois:

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

EDIT

est ici un approche intéressante publiée par Wojciech Sobala sur le other thread cela est lié à (je leur ai demandé de répondre ici et si ils le font, je vais retirer t son édition)

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

En fonction:

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

Toutes les grandes réponses, mais je pense que X , Il est le plus court code-sage. Merci, ça m'embêtait. Toutes les meilleures approches que ce que je faisais. –

Répondre

5

Je ne sais pas si cela fait le travail?

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 
} 

Edit: a changé la sortie à une liste

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

Très simple. +1 –

+0

@ tyler-rinker Bien que je ne sache pas si c'est rapide ... – Alex

+0

Ce n'est pas une liste mais ça ne marchera pas dans la question de cette affiche à moins que vous n'emballiez 'output' avec' 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

Je n'ai pas réellement édité votre réponse juste mis mon édition au mauvais endroit, des excuses. +1 –

3

Ce n'est pas le plus court, mais voici une version peu récursive:

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, celui-ci fait mal à mes nouilles. +1 Je ne suis même pas sûr de la façon dont cela fonctionne (bien que les indices soient dans l'ordre inverse) –

+1

Pour comprendre les fonctions récursives, il est parfois utile de suivre la chaîne des appels de fonction avec du papier et un crayon. Ou mettre quelques déclarations d'impression là-bas pour regarder la liste se développer et le vecteur se rétrécir. –

Questions connexes