rjss
rjss

Reputation: 1013

Paste items in a list where some of the items contain a vector

I am trying to build a query for an API and I have a function that is my parameters and values in a list. I am having problems if some of my parameters have multiple values. For example,

paramlist1 <- list(
  a = "1",
  b = "2",
  c = "3",
  d = "4"
)
paste(names(paramlist1), "=", paramlist1, collapse = "&", sep="")

works fine. But I have some parameters that can contain multiple values. For example,

paramlist2 <- list(
  a = "1",
  b = "2",
  c = c("3", "4"),
  d = c("5", "6")
)

I would like this to return me 2 strings: a=1&b=2&c=3&d=5 and a=1&b=2&c=4&d=6

Maybe my approach to create this parameter list is not the best. Thanks

Upvotes: 3

Views: 111

Answers (3)

akrun
akrun

Reputation: 887213

We check the lengths of the list, get the max length ('mx'), based on that append the paramlist2 elements that have shorter length with NA, stack it to a two column data.frame, fill the NA elements with the non-NA adjacent elements above, grouped by 'ind', create a sequence column, and then summarise the 'ind' and 'value' by pasteing the elements grouped by 'n'

library(tidyverse)
fn1 <- function(lst) {
    mx <- max(lengths(lst))
    map(lst, `length<-`, mx) %>%
        stack %>%
        fill(values) %>% 
        group_by(ind) %>% 
        mutate(n = row_number()) %>% 
        group_by(n) %>% 
        summarise(val = paste(ind, "=", values, collapse= "&", sep=""))
}

fn1(paramlist2)
# A tibble: 2 x 2
#      n val            
#  <int> <chr>          
#1     1 a=1&b=2&c=3&d=5
#2     2 a=1&b=2&c=4&d=6

On another list with different length of each elements 1, 2, and 3.

paramlist3 <- list(a = "1", b = "2", c = c("3", "4", "6"), d = c("5", "6"))
fn1(paramlist3)
# A tibble: 3 x 2
#     n val            
#  <int> <chr>          
#1     1 a=1&b=2&c=3&d=5
#2     2 a=1&b=2&c=4&d=6
#3     3 a=1&b=2&c=6&d=6

Here, we are assuming that the last non-NA element repeats itself to adjust the length

Upvotes: 1

AndS.
AndS.

Reputation: 8110

Here is another option. It looks like when you convert the list to a dataframe, it fills in the extra numbers for you. Then we just gather the results and summarize the output.

library(tidyverse)

paramlist2 <- list(
  a = "1",
  b = "2",
  c = c("3", "4"),
  d = c("5", "6")
)

paramlist2 %>% 
  as.data.frame() %>% 
  rownames_to_column("row") %>%
  gather(col, num, -row) %>%
  group_by(row) %>%
  summarise(result = paste(col, "=", num, sep = "", collapse = "&"))

#> # A tibble: 2 x 2
#>   row   result         
#>   <chr> <chr>          
#> 1 1     a=1&b=2&c=3&d=5
#> 2 2     a=1&b=2&c=4&d=6

Created on 2018-09-20 by the reprex package (v0.2.0).

Upvotes: 1

DanY
DanY

Reputation: 6073

You need to repeat the shorter vectors to be the same length as the longer vectors. One way to do this is to convert the list to a data.frame, then you can apply your paste function to each row:

myfun <- function(x) paste(names(x), "=", x, collapse="&", sep="")

apply(as.data.frame(paramlist2), 1, myfun)

Upvotes: 5

Related Questions