2017-05-01 1 views
1

Quel est le meilleur moyen de générer toutes les combinaisons d'une liste, où chaque combinaison contient tous les éléments de la liste et où vous pouvez combiner d'autres éléments.Générer toutes les combinaisons ordonnées d'une liste, où chaque combinaison comprend tous les éléments

Par exemple, pour une liste ['a','b','c'], j'aime générer:

['a','b','c'] 
['ab','c'] 
['a','bc'] 
['abc'] 

Je trouve un peu semblable à: Python: Generating all ordered combinations of a list. Mais celui-ci ne se soucie que des tranches. Je veux toutes les combinaisons qui prennent chaque article de la liste. Y a-t-il une fonction intégrée d'itertools qui peut être utilisée pour générer la réponse?

La liste pourrait aussi être des nombres qui pourraient avoir des valeurs en double. Par exemple: [1,2,1] devrait générer:

[1,2,1] 
[12,1] 
[1,21] 
[121] 

Je pourrais essayer d'utiliser le code du lien, mais au lieu de générer des combinaisons des éléments, je générer la base de combinaisons sur l'indice de la liste. Où je prends toutes les combinaisons qui commencent par 0, puis recherchez l'élément suivant et recherchez toutes les combinaisons qui commencent par cet élément et ainsi de suite. Je ne pense pas que ce serait efficace cependant.

Répondre

1

Vous pouvez considérer deux caractères adjacents de votre chaîne comme étant "séparés" ou "concaténés". L'utilisation itertools.product() vous pouvez générer toutes les combinaisons de séparation/concaténé entre deux caractères, puis utiliser une fonction simple pour générer une liste de chaînes de cette information:

import itertools 

l = ['a','b','c'] 

def generate_combination(source, comb): 
    res = [] 
    for x, action in zip(source,comb + (0,)): 
     res.append(x) 
     if action == 0: 
      yield "".join(res) 
      res = [] 

print [list(generate_combination(l,c)) 
     for c in itertools.product((0,1), repeat=len(l)-1)] 

Cela ne fonctionne pas pour les numéros bien à moins que vous les convertir en cordes d'abord.

+0

Cela semble fonctionner très bien. J'essaie juste de voir comment ça fonctionne. – user1179317

+0

Je viens de comprendre votre fonction de générateur, c'est plutôt cool. Merci d'avoir répondu. – user1179317

1

Voici un code supplémentaire pour que la réponse @acidtobi fonctionne à la fois pour int et char à l'aide de .isdigit().

final = [list(generate_combination(l,c)) 
     for c in itertools.product((0,1), repeat=len(l)-1)] 

print [[int(i) if i.isdigit() else i for i in alist ] for alist in final] 

Donc, pour l = [ 1,2,3], il montrera

>>> 
[[1, 2, 3], [1, 23], [12, 3], [123]] 

Et pour l = ['a','b','c']

>>> 
[['a', 'b', 'c'], ['a', 'bc'], ['ab', 'c'], ['abc']] 
1
import numpy as np 
l = ['a','b','c','d'] 
#l = [0,1,2,3] 
d = np.arange(2**(len(l)-1)) 
#create a separator array for all possible combinations 
sep = np.where((d[:,None] & (1 << np.arange(len(l))[::-1])) > 0, ',','') 
#merge the separator to the strings 
merged = np.core.defchararray.add(sep,np.asarray(l,dtype=str)).tolist() 
#reformat and split 
[''.join(e).split(',') for e in merged] 

#works for any characters 
[['abcd'], 
['abc', 'd'], 
['ab', 'cd'], 
['ab', 'c', 'd'], 
['a', 'bcd'], 
['a', 'bc', 'd'], 
['a', 'b', 'cd'], 
['a', 'b', 'c', 'd']] 

Out[128]: 
[['0123'], 
['012', '3'], 
['01', '23'], 
['01', '2', '3'], 
['0', '123'], 
['0', '12', '3'], 
['0', '1', '23'], 
['0', '1', '2', '3']]