2013-08-27 2 views
5

J'ai un code très inefficace que je voudrais rendre plus général/efficace. J'essaie de créer des chaînes à partir d'un ensemble de listes.Manière efficace de créer des chaînes à partir d'une liste

Voici ce que j'ai actuellement:

#contains categories 
numind = [('Length',), ('Fungus',)] 

#contains values that pertain to the categories 
records = [('Length', 'Long'), ('Length', 'Med'), ('Fungus', 'Yes'), ('Fungus', 'No')] 

#contains every combination of values between the 2 categories. 
#for example, (Long, Yes) = Length=Long & Fungus = Yes. 
combinations = [('Long', 'Yes'), ('Long', 'No'), ('Med', 'Yes'), ('Med', 'No')] 

Maintenant, je veux créer des chaînes qui ont toutes les combinaisons dans ma liste de combinaison. C'est la partie inefficace. Je voudrais que je n'aie pas à câbler la longueur de la liste "numind". Des idées?

values = combinations 
valuestring = [] 

if len(numind) == 0: 
    pass 
elif len(numind) == 1: 
    for a in xrange(len(values)): 
     valuestring.append(numind[0][0]+values[a][0]) 

elif len(numind) == 2: 
    for a in xrange(len(values)): 
     valuestring.append(numind[0][0]+values[a][0]+'_'+numind[1][0]+values[a][1]) 

#and so forth until numind is 10+ 

sortie

['LengthLong_FungusYes', 'LengthLong_FungusNo', 'LengthMed_FungusYes', 'LengthMed_FungusNo'] 

Répondre

4

J'utilise itertools.product avec collections.OrderedDict (ce dernier n'est pas strictement nécessaire, mais signifie que vous obtenez le bon ordre sans avoir à y penser):

>>> from collections import OrderedDict 
>>> from itertools import product 
>>> 
>>> d = OrderedDict() 
>>> for k, v in records: 
...  d.setdefault(k, []).append(v) 
...  
>>> d 
OrderedDict([('Length', ['Long', 'Med']), ('Fungus', ['Yes', 'No'])]) 
>>> ['_'.join(k+v for k,v in zip(d, v)) for v in product(*d.values())] 
['LengthLong_FungusYes', 'LengthLong_FungusNo', 'LengthMed_FungusYes', 'LengthMed_FungusNo'] 

itertools.product produit naturellement la partie «toutes les combinaisons» (ce qui est vraiment appelé le produit cartésien, pas une combinaison):

>>> product(["Long", "Med"], ["Yes", "No"]) 
<itertools.product object at 0x96b0dec> 
>>> list(product(["Long", "Med"], ["Yes", "No"])) 
[('Long', 'Yes'), ('Long', 'No'), ('Med', 'Yes'), ('Med', 'No')] 

L'avantage ici est que peu importe combien de catégories il y a ou combien de valeurs il sont associés à une catégorie: aussi longtemps qu'ils sont spécifiés dans records, il devrait fonctionner.

+0

Génial! bon code homme. Appréciez l'explication aussi! – nlr25

0

Essayez d'utiliser itertools

s = 'Length%s_Fungus%s' 
l1 = ['Long', 'Med'] 
l2 = ['Yes', 'No'] 
[s%x for x in itertools.product(l1, l2)] 

Cela donne

['LenLong_FungusYes', 
'LenMed_FungusNo', 
'LenMed_FungusYes', 
'LenLong_FungusNo'] 
0
>>> numind = [('Length',), ('Fungus',)] 
>>> combinations = [('Long', 'Yes'), ('Long', 'No'), ('Med', 'Yes'), ('Med', 'No')] 
>>> ['_'.join(numind[i][0] + v for i, v in enumerate(c)) for c in combinations] 
['LengthLong_FungusYes', 'LengthLong_FungusNo', 'LengthMed_FungusYes', 'LengthMed_FungusNo'] 
0

Comment général voulez qu'il soit?

>>> for item in combinations: 
    '_'.join(map(''.join, zip(list(itertools.chain(*numind)), item))) 


'LengthLong_FungusYes' 
'LengthLong_FungusNo' 
'LengthMed_FungusYes' 
'LengthMed_FungusNo' 
Questions connexes