renkun-ken / rlist

A Toolbox for Non-Tabular Data Manipulation
Other
204 stars 28 forks source link

Recursive unlist to certain level #102

Closed renkun-ken closed 9 years ago

renkun-ken commented 9 years ago

In some cases one needs to unlist a deeply nested list by certain times to make a less nested list in which the first level is reasonably equal to others. For example,

a1:
  x1:
    y1:
      name: name1
      value: [1, 2, 3]
    y2:
      name: name2
      value: [2, 3, 5]
  x2:
    y2:
      name: name3
      value: [0, 0, 1]
a2:
  m1:
    y1:
      name: name4
      value: [1, 4, 2]
    y2:
      name: name5
      value: [0, 1, 0]
  m2:
    y3:
      name: name6
      value: [0, 1, 1]

unlist this data directly will result in

> z %>>% unlist
  a1.x1.y1.name a1.x1.y1.value1 a1.x1.y1.value2 a1.x1.y1.value3   a1.x1.y2.name a1.x1.y2.value1 a1.x1.y2.value2 a1.x1.y2.value3 
        "name1"             "1"             "2"             "3"         "name2"             "2"             "3"             "5" 
  a1.x2.y2.name a1.x2.y2.value1 a1.x2.y2.value2 a1.x2.y2.value3   a2.m1.y1.name a2.m1.y1.value1 a2.m1.y1.value2 a2.m1.y1.value3 
        "name3"             "0"             "0"             "1"         "name4"             "1"             "4"             "2" 
  a2.m1.y2.name a2.m1.y2.value1 a2.m1.y2.value2 a2.m1.y2.value3   a2.m2.y3.name a2.m2.y3.value1 a2.m2.y3.value2 a2.m2.y3.value3 
        "name5"             "0"             "1"             "0"         "name6"             "0"             "1"             "1" 

To unlist to the third level, one needs to unlist it with recursive = FALSE twice.

x %>>% unlist(recursive = FALSE) %>>% unlist(recursive = FALSE)

which produces a list with following structure

List of 6
 $ a1.x1.y1:List of 2
  ..$ name : chr "name1"
  ..$ value: int [1:3] 1 2 3
 $ a1.x1.y2:List of 2
  ..$ name : chr "name2"
  ..$ value: int [1:3] 2 3 5
 $ a1.x2.y2:List of 2
  ..$ name : chr "name3"
  ..$ value: int [1:3] 0 0 1
 $ a2.m1.y1:List of 2
  ..$ name : chr "name4"
  ..$ value: int [1:3] 1 4 2
 $ a2.m1.y2:List of 2
  ..$ name : chr "name5"
  ..$ value: int [1:3] 0 1 0
 $ a2.m2.y3:List of 2
  ..$ name : chr "name6"
  ..$ value: int [1:3] 0 1 1

which is desired.

Implement a function in rlist to perform unlist recursively.