René Nyffenegger
René Nyffenegger

Reputation: 40499

Is there a sprintf variant where the (only) vector's element are used in all % expansions?

I am wondering if there is a generic way in R to create character vectors from a template where the values of another vector are expanded in an arbitrary number of times.

That is, I am looking for a function like tq84(template, vec) that I could call with tq84('foo_%d, bar_%d, baz_%d', 1:2) and then results in the vector "foo_1, bar_1, baz_1", "foo_2, bar_2, baz_2". Note that the length of the resulting vector should be equal to the length of the input vector.

Upvotes: 0

Views: 94

Answers (3)

akrun
akrun

Reputation: 887088

May be we can use the rep

tq84 <- function(template, vec) {
             paste(template, rep(vec, each = length(template)), sep="_")
 }
v1 <- c("foo", "bar", "baz")
tq84(v1, 1:2)
#[1] "foo_1" "bar_1" "baz_1" "foo_2" "bar_2" "baz_2"

If we need a single string that exactly matches the expected output

tq84n <- function(template, vec) {
       sapply(as.list(vec), function(x) paste(template, x, sep="_",
          collapse=" "))
 }
tq84n(v1, 1:2)
#[1] "foo_1 bar_1 baz_1" "foo_2 bar_2 baz_2"

Or another option is to use crossing and then do a group_by paste

library(tidyverse)
tq84n2 <- function(template, vec) {
     crossing(template, grp = vec) %>% 
         unite(template, template, grp, remove = FALSE) %>%
          group_by(grp) %>%
          summarise(template = str_c(template, collapse=" ")) %>%
          pull(template)
  }
tq84n2(v1, 1:2)
#[1] "bar_1 baz_1 foo_1" "bar_2 baz_2 foo_2"

Upvotes: 2

Ronak Shah
Ronak Shah

Reputation: 388972

Maybe , we can use outer with paste

vec <- c("foo", "bar", "vec")
c(outer(vec, 1:2, paste, sep = "_"))
#[1] "foo_1" "bar_1" "vec_1" "foo_2" "bar_2" "vec_2"

Or if you want to keep them separate we can skip c

outer(vec, 1:2, paste, sep = "_")

#        [,1]    [,2]   
#[1,] "foo_1" "foo_2"
#[2,] "bar_1" "bar_2"
#[3,] "vec_1" "vec_2"

Or to exactly match the expected output

apply(outer(vec, 1:2, paste, sep = "_"), 2, paste, collapse = ", ") 
#[1] "foo_1, bar_1, vec_1" "foo_2, bar_2, vec_2"

Upvotes: 1

NelsonGon
NelsonGon

Reputation: 13319

A Map alternative that returns a list:

     tq84 <- function(vec, numbers){
   Map(function(x)
     paste0(vec[x],"_",numbers),
     seq_along(vec))
 }
 foobar <- c("foo","bar","baz")
 tq84(foobar,1:2)
[[1]]
[1] "foo_1" "foo_2"

[[2]]
[1] "bar_1" "bar_2"

[[3]]
[1] "baz_1" "baz_2"

Upvotes: 1

Related Questions