2012-05-19 12 views
5

W pytaniu tutaj na SO (LINK) plakat zadał pytanie, a ja dałem odpowiedź, która działa, ale jest część, która mnie burzy, tworząc list z wektora, aby przekazać jako lista indeksów. Więc les, że mam ten wektor:Zrób listę wektorów o równej długości.

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

Powiedzmy, że chcesz podzielić ją na listę wektorach i każdy wektor ma długość 3. Jaki jest najlepszy (najkrótszy ilość kodu & lub najszybsze) sposób osiągnąć to? Chcemy rzucić item 10, ponieważ pozostała część 1 (10 %% 3) z 10/3 (length(n) - 10 %% 3).

Jest to pożądany efekt

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

To da nam indeksy tych, które nie mogą dokonać grupa trzech:

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

EDIT

Oto ciekawe podejście zamieszczone przez Wojciecha Sobala na other thread jest to związane z (poprosiłem ich o odpowiedź tutaj, a jeśli to zrobię, usuniemy t jego edycja)

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

Jako funkcję:

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

Wszystkie wielkie odpowiedzi, ale myślę, że X On jest najkrótszym kodem. Dzięki, to mnie wkurzyło. O wiele lepsze podejście niż to, co robiłem. –

Odpowiedz

5

Nie wiem, czy to spełnia swoje zadanie?

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 
} 

Edycja: zmieniono wyjście do listy

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

Bardzo proste. +1 –

+0

@ tyler-rinker Chociaż nie jestem pewien, czy jest szybki ... – Alex

+0

To nie jest lista, więc nie będzie działać w pytaniu tego plakatu, chyba że zawiniesz 'output' z' 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

Naprawdę nie edytowałem twojej odpowiedzi, po prostu umieść moją edycję w niewłaściwym miejscu, przepraszam. +1 –

3

To nie jest najkrótsza, ale tutaj jest trochę rekurencyjna wersja:

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 to boli mojego kluska. +1 Nie jestem nawet pewien jak to działa (chociaż indeksy są w odwrotnej kolejności) –

+1

Aby zrozumieć funkcje rekurencyjne, czasami pomocne może być śledzenie łańcucha wywołań funkcji za pomocą papieru i ołówka. Lub umieść tam kilka instrukcji drukowania, aby zobaczyć, jak lista rośnie, a wektor się kurczy. –

Powiązane problemy