5

より一般的/効率的にしたい非常に非効率的なコードがあります。リストのセットから文字列を作成しようとしています。

これが私が現在持っているものです:

#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')] 

ここで、組み合わせリストにすべての組み合わせを含む文字列を作成したいと考えています。これは非効率な部分です。「numind」リストの長さを固定する必要がないようにしたいと思います。何か案は?

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+

出力

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

4 に答える 4

4

私は次のように使用itertools.productしますcollections.OrderedDict(後者は厳密には必要ではありませんが、考えなくても正しい順序で注文できることを意味します):

>>> 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自然に「すべての組み合わせ」部分が生成されます (これは、実際には組み合わせではなくデカルト積と呼ばれます)。

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

ここでの利点は、カテゴリがいくつあっても、カテゴリに関連付けられている値がいくつあってもかまわないということですrecords

于 2013-08-27T19:19:56.247 に答える
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']
于 2013-08-27T19:25:51.210 に答える
0

どれくらい一般的になりたいですか?

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


'LengthLong_FungusYes'
'LengthLong_FungusNo'
'LengthMed_FungusYes'
'LengthMed_FungusNo'
于 2013-08-27T19:30:55.867 に答える
0

itertools を使ってみる

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

これにより、

['LenLong_FungusYes',
 'LenMed_FungusNo',
 'LenMed_FungusYes',
 'LenLong_FungusNo']
于 2013-08-27T19:22:15.477 に答える