2012-05-19 11 views
5

In einer Frage hier auf SO (LINK) ein Plakat stellte eine Frage, und ich gab eine Antwort, die funktioniert, aber es gibt einen Teil, der mich stört, ein list aus einem Vektor zu erstellen, um als Liste zu übergeben von Indizes. So les sagen, ich habe diesen Vektor:Machen Sie eine Liste der gleichen Länge Vektoren

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

Sagen wir, ich möchte es in eine Liste von Vektoren brechen und jeder Vektor ist der Länge 3. Was ist der beste (kürzeste Code & oder am schnellsten) Weg dies erreichen? Wir wollen Artikel 10 wegwerfen, da es einen Rest von 1 (10 %% 3) vom 03.10. (length(n) - 10 %% 3) gibt.

Dies ist das gewünschte Ergebnis

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

Dies gibt uns die Indizes von denen, die nicht eine Gruppe von drei machen können:

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

EDIT

Hier ein Interessanter Ansatz geschrieben von Wojciech Sobala auf der other thread das ist verknüpft mit (Ich bat sie, hier zu antworten, und wenn sie das tun, werde ich t entfernen seine bearbeiten)

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

Als Funktion:

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

Alle großen Antworten, aber ich denke X , Er ist der kürzeste Code-weise. Danke, das nervte mich. Alles viel bessere Ansätze als was ich tat. –

Antwort

5

nicht sicher, ob dies die Arbeit erledigt?

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: verändert die Ausgabe in eine 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

Sehr einfach. +1 –

+0

@ tyler-rinker Obwohl ich bin mir nicht sicher, ob es schnell ist ... – Alex

+0

Es ist nicht eine Liste, also wird es in der Frage dieses Posters nicht funktionieren, es sei denn, Sie wickeln die 'Ausgabe' mit' 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

Ich habe deine Antwort nicht bearbeitet, sondern meine Bearbeitung an die falsche Stelle gesetzt, entschuldige mich. +1 –

3

Es ist nicht der kürzeste, aber hier ist ein wenig rekursive Version:

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, das tut meiner Nudel weh. +1 Ich bin mir nicht einmal sicher, wie es funktioniert (obwohl Indizes in umgekehrter Reihenfolge sind) –

+1

Um rekursive Funktionen zu verstehen, kann manchmal das Folgen der Kette von Funktionsaufrufen mit Papier und Bleistift helfen. Oder fügen Sie ein paar Druckanweisungen ein, um die Liste zu vergrößern und den Vektor zu verkleinern. –

Verwandte Themen