2013-02-26 2 views
1

Предположим, у меня есть три слова: "blue", "red" и "pink".Объединения из рекурсивных списков

Я хочу сгенерировать все комбинации букв, в которых я беру две буквы из «синего», а затем добавить к двум буквам из «красного», а затем добавить к двум буквам из «розового», например.

blrdpk

uerdin

и т.д ...

В R, я закодированы три мои слова, назначая символы каждого слова в список элементов с помощью

words <- list(list("b","l","u","e"), list("r","e","d"), list("p","i","n","k")) 

Я знаю, что могу использовать lapply с combn(words[[i]],m=2), чтобы получить все комбинации из 2 lett из каждого слова.

У меня есть два вопроса:

  1. Есть более продвинутая версия combn(), который позволяет выбрать и объединить комбинации из различных «ковши» с учетом использования рекурсивных списков?

  2. Если нет расширенной версии combn(), то какой лучший способ объединить каждую из двух комбинаций букв из каждого из трех слов?

  3. Есть ли простой способ сделать это, если мне нужно различное количество букв от каждого слова? [Добавлено от пользователя комментарий в одном из ответа]

+0

Имеет ли значение порядок букв? –

+0

Заказ букв не имеет значения. – Alex

+0

Кроме того, я просто читал, и, чтобы ответить на вопрос 2, я могу, вероятно, просто использовать expand.grid() – Alex

ответ

4

Там могут быть более продвинутые версии combn, но это довольно продвинутый уже. Например, вы можете применить функцию к каждой комбинации, указав аргумент FUN. В сочетании с expand.grid и уменьшить, и вы будете возится с чем-то вроде

Reduce(paste0, expand.grid(lapply(words, function(x) { 
    combn(x, m=2, FUN=paste0, collapse="") 
}))) 

Edit: Если количество букв, которые будут выбраны из каждого слова меняется, это число может быть добавлен в качестве атрибута каждого элемента списка слов, затем используйте этот атрибут как аргумент m для combn. Например, чтобы выбрать одну букву для первого слова, два письма от второго, и три буквы от третьего:

for(i in seq_along(words)) { 
    attr(words[[i]], "n") <- i 
} 

Reduce(paste0, expand.grid(lapply(words, function(x) { 
    combn(x, m=attr(x, "n"), FUN=paste0, collapse="")}))) 

В качестве альтернативы вы можете использовать mapply как в ответ geektrader в.

+0

. Есть ли простой способ сделать это, если я захочу разного количества писем от каждого слова? – Alex

2

Здесь решение происходит из списка слов и список количества символов ковыряться от каждого слова желаемого результата

> words 
[1] "blue" "red" "pink" 
> wordsplit <- strsplit(words, split="") 
> wordsplit 
[[1]] 
[1] "b" "l" "u" "e" 

[[2]] 
[1] "r" "e" "d" 

[[3]] 
[1] "p" "i" "n" "k" 

> lengths <- c(2, 1, 3) 
> combos <- expand.grid(mapply(function(word, n) combn(word,m=n, FUN=paste0, collapse=""), wordsplit, lengths)) 
> head(combos) 
    Var1 Var2 Var3 
1 bl r pin 
2 bu r pin 
3 be r pin 
4 lu r pin 
5 le r pin 
6 ue r pin 

> do.call('paste0', combos) 
[1] "blrpin" "burpin" "berpin" "lurpin" "lerpin" "uerpin" "blepin" "buepin" "beepin" "luepin" "leepin" "ueepin" "bldpin" "budpin" "bedpin" "ludpin" 
[17] "ledpin" "uedpin" "blrpik" "burpik" "berpik" "lurpik" "lerpik" "uerpik" "blepik" "buepik" "beepik" "luepik" "leepik" "ueepik" "bldpik" "budpik" 
[33] "bedpik" "ludpik" "ledpik" "uedpik" "blrpnk" "burpnk" "berpnk" "lurpnk" "lerpnk" "uerpnk" "blepnk" "buepnk" "beepnk" "luepnk" "leepnk" "ueepnk" 
[49] "bldpnk" "budpnk" "bedpnk" "ludpnk" "ledpnk" "uedpnk" "blrink" "burink" "berink" "lurink" "lerink" "uerink" "bleink" "bueink" "beeink" "lueink" 
[65] "leeink" "ueeink" "bldink" "budink" "bedink" "ludink" "ledink" "uedink" 
Смежные вопросы