2

I have a vector of words:

str <- c("The", "Cat", "Jumped")

I would like to find all combinations of words and insert a "+" between any combinations of more than one, similar to:

paste(str, collapse = " + ")
# [1] "The + Cat + Jumped"

My desired output would be:

want <- c("The", "Cat", "Jumped", 
          "The + Cat", "The + Jumped",
          "Cat + Jumped",
          "The + Cat + Jumped")

Also note I need only combinations so order doesn't matter and either "The + Cat" or "Cat + The" is fine, but I do not want both.


I tried some approaches with combn (here), outer (here), expand.grid (here), and following @Akrun's suggestion on a similar question r - Get different combinations of words but to no avail.

ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
jpsmith
  • 11,023
  • 5
  • 15
  • 36

5 Answers5

4

You can use combn for all possible sizes, and then collapse the results yourself

str <- c("The", "Cat", "Jumped")
Map(function(i) combn(str, i, simplify = FALSE), seq_along(str)) |>
  unlist(recursive=FALSE) |> 
  sapply(paste, collapse=" + ")
# [1] "The"                "Cat"                "Jumped"            
# [4] "The + Cat"          "The + Jumped"       "Cat + Jumped"      
# [7] "The + Cat + Jumped"
MrFlick
  • 195,160
  • 17
  • 277
  • 295
4

You can play a trick with intToBits like below

lapply(
  1:(2^length(str) - 1),
  function(k) {
    paste0(str[which(intToBits(k) == 1)], collapse = " + ")
  }
)

which gives

[[1]]
[1] "The"

[[2]]
[1] "Cat"

[[3]]
[1] "The + Cat"

[[4]]
[1] "Jumped"

[[5]]
[1] "The + Jumped"

[[6]]
[1] "Cat + Jumped"

[[7]]
[1] "The + Cat + Jumped"
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
3
unlist(lapply(seq(str), combn, x=str, paste, collapse=' + '))

[1] "The"                "Cat"                "Jumped"             "The + Cat"          "The + Jumped"      
[6] "Cat + Jumped"       "The + Cat + Jumped"
Onyambu
  • 67,392
  • 3
  • 24
  • 53
3

Here is tidyverse variation of @MrFlick s code:

library(tidyverse)

str <- c("The", "Cat", "Jumped")

map(1:length(str), function(i) {
  combn(str, i, simplify = FALSE) %>%
    map(~paste(., collapse = " + "))
  }) %>%
  unlist(recursive = FALSE) %>% 
  unlist()
[1] "The"                "Cat"               
[3] "Jumped"             "The + Cat"         
[5] "The + Jumped"       "Cat + Jumped"      
[7] "The + Cat + Jumped"
TarJae
  • 72,363
  • 6
  • 19
  • 66
2

Using the powerSet function from the rje package:

lapply(rje::powerSet(str), paste, collapse = " + ")
#> [[1]]
#> [1] ""
#> 
#> [[2]]
#> [1] "The"
#> 
#> [[3]]
#> [1] "Cat"
#> 
#> [[4]]
#> [1] "The + Cat"
#> 
#> [[5]]
#> [1] "Jumped"
#> 
#> [[6]]
#> [1] "The + Jumped"
#> 
#> [[7]]
#> [1] "Cat + Jumped"
#> 
#> [[8]]
#> [1] "The + Cat + Jumped"

N.B. The first element corresponds to the empty set. See the wiki for the Power set for more information.

Joseph Wood
  • 7,077
  • 2
  • 30
  • 65