-1

I have the following list and index range reference for a function below with desired output. My aim is to select and group for the main lists sublists as per an index list selection range indicated by A and E. Have tried in two ways but can not seem to be able to acomplish this.

RECX5  <- list ( list ( c( 1 , 2 , 3 , 4 , 5 ) , c( 6 , 7 , 8 , 9 , 10 ) , c( 11 , 12 , 13 , 14, 15 )) , list (c( -11 , -12 , -13 , -14 , -15 ) , c( 16 , 17 , 18 , 19 , 20 ) , c( 21 , 22 , 23 , 24, 25 ))) 

# SUB-SELECT LISTS 
A <- c(1,2)

# SELECT RANGE FOR LISTS
E <- data.frame ( c(1,2) , c(1,5))

for ( i in seq(nrow(E)) )
fun <-  function ( x ) RECX5 [[ x ]] [ E[ ,1 ] [[ i ]] : E[ ,2 ] [[ i ]] ] 
D   <-  lapply (  seq(length ( A )) , fun )
# D
[[1]]
[[1]][[1]]
[1]  6  7  8  9 10

[[1]][[2]]
[1] 11 12 13 14 15

[[1]][[3]]
NULL

[[1]][[4]]
NULL


[[2]]
[[2]][[1]]
[1] 16 17 18 19 20

[[2]][[2]]
[1] 21 22 23 24 25

[[2]][[3]]
NULL

[[2]][[4]]
NULL


DESIRED RESULT : 
[[1]]
[[1]][[1]]
1  2  3  4  5 
[[1]][[2]]
-11 -12 -13 -14 -15   

[[2]]
[[2]][[1]][[1]]
6  7  8  9 10 
[[2][[1]][[2]]
16 17 18  19  20 
[[2]][[2]][[1]]
11 12 13 14 15 
[[2]][[2]][[2]]
21 22 23 24 25 
Barnaby
  • 1,472
  • 4
  • 20
  • 34
  • 1
    Appologies corrected it seq missing, thanks – Barnaby Apr 04 '16 at 19:45
  • I don't understand this question "generically." First--in your desired output, I assume you are using shorthand and mean for your single brackets to be double brackets? Single `[` and double `[[` have different [meaning](http://stackoverflow.com/a/1169495/241643) in `R`, which may be part of your difficulty... – Philip Apr 04 '16 at 20:04
  • Second, assuming the answer to above is yes, the desired result is just a slight restructuring of a nested list into a different nested list. But do you literally mean that you want exactly to take a length-2 list of length-3 lists of length-5 vectors, and turn that into a length-2 list, where the first element in that list is a length-2 list of length-5 vectors, and the second is a length-2 list of length-2 lists of length-5 vectors? Or do you want to do something more general? – Philip Apr 04 '16 at 20:06
  • Generic meant to avoid having someone answering fun <- function ( x ) RECX5 [[ x ]] [ E[ ,1 ] [[ 1 ]] : E[ ,2 ] [[ 1 ]] ] D <- lapply ( seq(length ( A )) , fun ) and doing the same for the second which will yield the desired result. And yes I mean double brackets (Editing it) – Barnaby Apr 04 '16 at 20:11
  • I'm still confused about what your overall request is, but tell me what's insufficient about the answer I'm about to post and we can iteratively generalize it. – Philip Apr 04 '16 at 20:12
  • extract sublists as per index and group the extrated lists as per the two index range. Appologies if incorrectly framed. – Barnaby Apr 04 '16 at 20:15

2 Answers2

-1

This produces the intended structure, but is obviously not generic:

> list(list(RECX5[[1]][[1]],RECX5[[2]][[1]]),
+      list(list(RECX5[[1]][[2]],RECX5[[2]][[2]]),
+           list(RECX5[[1]][[3]],RECX5[[2]][[3]])))
[[1]]
[[1]][[1]]
[1] 1 2 3 4 5

[[1]][[2]]
[1] -11 -12 -13 -14 -15


[[2]]
[[2]][[1]]
[[2]][[1]][[1]]
[1]  6  7  8  9 10

[[2]][[1]][[2]]
[1] 16 17 18 19 20


[[2]][[2]]
[[2]][[2]][[1]]
[1] 11 12 13 14 15

[[2]][[2]][[2]]
[1] 21 22 23 24 25

What do you want more generally? Generally speaking [sorry], you can generalize the above by just picking an indexing level and then lapplying some range of indices function(x) [that expression] where the multiple calls over the index level you want to functionalize are replaced with x.

EDIT/UPDATE

Per my several comments I don't understand how you think you're generically specifying input to your solution, but I've spelled out an approach here that should indicate what the requirements are for a solution. Ideally, you can simplify this strategy if you actually do have some assumptions that hold that I haven't hard-coded in.

Note, yes, this solution is still not generic in handling result lists of arbitrary depth. That is doable, but an even bigger mess.

First: let's walk the list to build its structure as a table. This will make it easier to traverse the list in the eventual function call:

library(data.table)
build.structure <- function(src) {
    rbindlist(lapply(1:length(src),
              function(x) data.table(input.position.depth.0=rep(x,length(src[[x]])),
                                     input.position.depth.1=1:length(src[[x]]))))
}

struct <- build.structure(RECX5)
> struct
   input.position.depth.0 input.position.depth.1
1:                      1                      1
2:                      1                      2
3:                      1                      3
4:                      2                      1
5:                      2                      2
6:                      2                      3

Now manually build the desired result structure that you'll pass to the function. This is where I don't understand what you've tried to do. Somehow the result function needs all this information: where will each element from the input get put precisely in the list structure of the output? I've made this excruciatingly specific in this example, but if you have simplifying assumptions, you'll be able to skip some of this detail:

struct[,result.position.depth.0:=c( 1, 2, 2,  1, 2, 2)]
struct[,result.position.depth.1:=c( 1, 1, 2,  2, 1, 2)]
struct[,result.position.depth.2:=c(NA, 1, 1, NA, 2, 2)]

Note reading down this text in a column is the resulting list position for the element; when you display the table you read across:

> struct
   input.position.depth.0 input.position.depth.1 result.position.depth.0 result.position.depth.1
1:                      1                      1                       1                       1
2:                      2                      1                       1                       2
3:                      1                      2                       2                       1
4:                      2                      2                       2                       1
5:                      1                      3                       2                       2
6:                      2                      3                       2                       2
   result.position.depth.2
1:                      NA
2:                      NA
3:                       1
4:                       2
5:                       1
6:                       2

The function I write below assumes the new list is built in dictionary order of elements via depth indexing, so sort this table accordingly:

setkey(struct,result.position.depth.0,
              result.position.depth.1,
              result.position.depth.2)

(Note, there is a breakdown in generality here. If you need this to go even deeper than 2 levels, melt the data and add an additional depth column to refer to the depth as that column's value, and modify below accordingly to pluck the depth out rather than hard-coding the intended depth.)

Now a convenience function to extract data from the input list as specified by the row in the table we just built:

extract <- function(src,struct,a.row) {
    src[[struct[a.row,input.position.depth.0]]][[struct[a.row,input.position.depth.1]]]
}

Now the long part.

First make a global object. (This just means we don't have to worry about references. This can be avoided, but I'm not going to bother.)

result <<- list()

Then let's use a function that modifies this object [see comments inline]

get.lists.from.structure <- function(src, struct) {
    lapply(1:nrow(struct), function(the.row) {
           #Extract the value that we'll insert next
           val <- extract(src,struct,the.row)

           #If there's not already a slot at the top level for this value,
           #make an empty list there so we'll have a place to put it.
           #Without this you'll get subscript out of bounds errors
           if(length(result) < struct[the.row,result.position.depth.0]) {
               result[[struct[the.row,result.position.depth.0]]] <<- list()
           }

           #Now if the resulting object is getting stuck one level down,
           #take the first branch; just put it there.
           if(struct[the.row,is.na(result.position.depth.2)]) {
               result[[struct[the.row,result.position.depth.0
                  ]]][[struct[the.row,result.position.depth.1]]] <<- val
           } else { 
           #otherwise, take this branch, but WAIT! Repeat the same check;
           #if there's not already a slot at this depth, put
           #an empty list in
               if(length(result[[struct[the.row,result.position.depth.0]]]) < 
                    struct[the.row,result.position.depth.1]) {
                   result[[struct[the.row,result.position.depth.0
                        ]]][[struct[the.row,result.position.depth.1]]] <<- list()
               }

               #then put the value in at its intended position.
               result[[struct[the.row,result.position.depth.0
                  ]]][[struct[the.row,result.position.depth.1
                  ]]][[struct[the.row,result.position.depth.2]]] <<- val
           }
    })
}

OK, now we can run this (ignore what it prints, or add an invisible)

get.lists.from.structure(RECX5,struct)

And check that it had the correct side effect on result:

> result
[[1]]
[[1]][[1]]
[1] 1 2 3 4 5

[[1]][[2]]
[1] -11 -12 -13 -14 -15


[[2]]
[[2]][[1]]
[[2]][[1]][[1]]
[1]  6  7  8  9 10

[[2]][[1]][[2]]
[1] 16 17 18 19 20


[[2]][[2]]
[[2]][[2]][[1]]
[1] 11 12 13 14 15

[[2]][[2]][[2]]
[1] 21 22 23 24 25
Philip
  • 7,253
  • 3
  • 23
  • 31
  • This is just an indexed list of the list in the question, changing the location of the sublists in the list. I aim to have a function where from the original order list I can extract sublists of interests as per an index range that indicates the possition in the main list and have those lists listed as per the index. – Barnaby Apr 04 '16 at 20:26
  • But you haven't specified how you're encoding the structure of the desired output list in your inputs. I don't see how you get to `List of 2 $ :List of 2 ..$ : num [1:5] 1 2 3 4 5 ..$ : num [1:5] -11 -12 -13 -14 -15 $ :List of 2 ..$ :List of 2 .. ..$ : num [1:5] 6 7 8 9 10 .. ..$ : num [1:5] 16 17 18 19 20 ..$ :List of 2 .. ..$ : num [1:5] 11 12 13 14 15 .. ..$ : num [1:5] 21 22 23 24 25` from your `A` and `E`. This is why I'm asking you what part is generic. Is the result *always* such a list, just with different sources? Or is the result of variable structure too? – Philip Apr 04 '16 at 20:32
  • In particular you have the numbers 2 and 5 in your input object `E`, but you'll see the number 5 never appears in the "correct answer" for the case you're giving as an example. So somehow there must be some unstated assumption; any generic function that takes your example input has to produce the output in the answer here, which means it somehow has to know to compute from the number 5 one of the magic numbers (indices, all 1 2 or 3) in my answer. Does this make sense? – Philip Apr 04 '16 at 20:36
  • My assumption which seems to be wrong or possible not complete is if I can write a loop for the function and if this function can take the value of first x and evaluate all values of i and then move to the next value of x and do the same. – Barnaby Apr 04 '16 at 20:50
  • lapply ( list name , '[' , list number )) will do – Barnaby Apr 05 '16 at 16:30
-1
Use : lapply ( list name , '[' ,  list number )


RECX5  <- list ( list ( c( 1 , 2 , 3 , 4 , 5 ) , c( 6 , 7 , 8 , 9 , 10 ) , c( 11 , 12 , 13 , 14, 15 )) , list (c( -11 , -12 , -13 , -14 , -15 ) , c( 16 , 17 , 18 , 19 , 20 ) , c( 21 , 22 , 23 , 24, 25 ))) 
# SUBSELECT LISTS. 
A       <-  c ( 1 , 2 )
# SELECT LISTS. 
B        <-  data.frame ( c ( 1 , 2 ) , c( 1 , 5 ))

# Possible solution, however I does the null results of running the sequence over the function so it adds two null list to at the end of the last lists.

fun     <-  function ( x ) ( B[,x] [2] - B[,x] [1] ) 
E1      <-  lapply ( seq ( nrow ( B )) , fun )
fun     <-  function ( x ) ( E[,2] [[x]] - E[,1] [[x]] )+1 
E1      <-  lapply ( seq ( nrow ( E )) , fun )
fun     <-  function ( x )  seq ( E1[[ x ]] )
E2      <-  lapply ( seq ( length ( E1 )) , fun )
E3      <-  relist ( seq ( unlist ( E2 )) , E2 )
fun    <- function ( y ) lapply ( RECX5 , '[' ,  unlist ( E3[ y ] ))
E4     <- lapply (seq(length(E3)) , fun )
Barnaby
  • 1,472
  • 4
  • 20
  • 34