Home > Software design >  get an argument list with sublists
get an argument list with sublists

Time:05-25

I would like to flatten this list of arguments

args <- list(
  a = 1,
  b = "2",
  list = list(c = 3, d = list(d1 = 5, d2 = 6)),
  e = data.frame(e1 = c("a", "b"), e2 = c(7, 8))
)

on this

args <- list(
  a = 1,
  b = "2",
  c = 3, 
  d = list(d1 = 5, d2 = 6),
  e = data.frame(e1 = c("a", "b"), e2 = c(7, 8))
)

Because I need get work this function call

g <- function(x, y, ...){
  do.call(f, x, y, ...)
}

g(x = x1, y = y1, args)

That does not work:

reduce(
  .x = args,
  .f = function(x) {
    ifelse(
      is.list(x),
      lapply(x, `[[`),
      x
    )
  }
)

that throws

Error in fn(out, elt, ...) : unused argument (elt)

CodePudding user response:

Update: to OPs new data:

purrr::c(flatten(args[1:3]), args[4])

$a
[1] 1

$b
[1] "2"

$c
[1] 3

$d
$d$d1
[1] 5

$d$d2
[1] 6


$e
  e1 e2
1  a  7
2  b  8

As you already state in your question "I would like to flatten this list of arguments" -> We could use purrrs flatten() function:

library(purrr)

flatten(args)
$a
[1] 1

$b
[1] "2"

$c
[1] 3

$d
$d$d1
[1] 5

$d$d2
[1] 6


$e
[1] 5

CodePudding user response:

You can try the code below using for loops

res <- c()
for (v in args) {
    if (is.list(v) & !is.data.frame(v)) {
        res <- c(res,v)
    } else {
        res <- c(res, list(v))
    }
}

or via Reduce

res <- Reduce(
    function(x,y) {
        c(x, ifelse(is.list(y) & !is.data.frame(y), I, list)(y))
    },
    args,
    c()
)

and you will obtain

> res
[[1]]
[1] 1

[[2]]
[1] "2"

$c
[1] 3

$d
$d$d1
[1] 5

$d$d2
[1] 6


[[5]]
  e1 e2
1  a  7
2  b  8

CodePudding user response:

The output of map always be the same dim. So you need a for loop.

output <- NULL
for (x in seq(length(args))) {
   list <- args[x]
  if (is.list(args[[x]]) && !is.data.frame(args[[x]])) {
    list <- flatten(args[x])
  }
  output <- append(output, list)
}
output
$a
[1] 1

$b
[1] "2"

$c
[1] 3

$d
$d$d1
[1] 5

$d$d2
[1] 6


$e
  e1 e2
1  a  7
2  b  8
  • Related