passing dots to function in map2

I have a list that I need to collapse into a string, preserving list names in the form name1=value1&name2=value2...

But i'm getting some unexpected behavior in passing arguments for .f to map2. I'm definitely missing something simple.

To be clear, the desired final value from the reprex is "people=amy&age=25&state=NY".

Any help is appreciated.

library(purrr)
library(dplyr) # because I use the pipe in my example
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

# a toy list
my_list <- list(people = "amy", age = 30, state = "NY" )

# DESIRED END RESULT IS A STRING: "people=amy&age=25&state=NY"


# why isn't the collapse argument making it to paste in map2() here?
yy <- my_list %>% map2(.x = names(.), .y = ., .f = paste, collapse = "=")
yy
#> [[1]]
#> [1] "people amy"
#> 
#> [[2]]
#> [1] "age 30"
#> 
#> [[3]]
#> [1] "state NY"

# this now adds the ampersand as expected
yy %>% unlist() %>% paste(collapse = "&")
#> [1] "people amy&age 30&state NY"

Created on 2018-10-07 by the reprex package (v0.2.1)

This has nothing to do with map2(). In general, before trying to apply a function on many elements through functional programming, it is a good idea to test it on one element first.

If you run your paste function on one element, you will see that it does not work any better.

The problem is that it is the argument sep (not collapse) that does what you want.

See the help file:

paste (..., sep = " ", collapse = NULL)

sep: a character string to separate the terms.  Not
          β€˜NA_character_’.

collapse: an optional character string to separate the results.  Not
          β€˜NA_character_’.
1 Like
library(purrr)
library(dplyr) # because I use the pipe in my example
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

# a toy list
my_list <- list(people = "amy", age = 30, state = "NY" )

# DESIRED END RESULT IS A STRING: "people=amy&age=25&state=NY"

yy <- my_list %>% map2(.x = names(.), .y = ., .f = paste, sep = "=")
yy
#> [[1]]
#> [1] "people=amy"
#> 
#> [[2]]
#> [1] "age=30"
#> 
#> [[3]]
#> [1] "state=NY"

# this now adds the ampersand as expected
yy %>% unlist() %>% paste(collapse = "&")
#> [1] "people=amy&age=30&state=NY"
3 Likes

What confused you is that paste() already applies functional programming. So you do not need to use map2().

my_list <- list(people = "amy", age = 30, state = "NY" )
paste(names(my_list), my_list, sep = "=", collapse = "&")
#> [1] "people=amy&age=30&state=NY"
1 Like

The sep argument applies within elements and the collapse argument applies between elements.

Note: while we explicitly use functional programming with the apply() or map() functions, a number of base R functions already do that. We just don't think about it that way.

1 Like