1

私はこのようなかなりばかげたリストを持っています。

[['Biking', '10'], ['Biking|Gym', '14'], ['Biking|Gym|Hiking', '9'], ['Biking|Gym|Hiking|Running', '27']]

次のように、['Type', total, %] の形式にしたいと思います。

[['Biking',60,'34.7%'],['Gym',50,'28.9%'],['Hiking',36,'20.8%'],['Running',27,'15.6%']]

私はこれを可能な限り最も困難な方法で行っていると確信しています-誰かが私をより良い方向に向けることができますか? 以前に itertools.groupby を使用したことがありますが、これは適切な場所のようですが、このシナリオで実装する方法がわかりません。

# TODO: This is totally ridiculous.
running = 0
hiking = 0
gym = 0
biking = 0
no_exercise = 0

for r in exercise_types_l:
    if 'Running' in r[0]:
        running += int(r[1])
    if 'Hiking' in r[0]:
        hiking += int(r[1])
    if 'Gym' in r[0]:
        gym += int(r[1])
    if 'Biking' in r[0]:
        biking += int(r[1])
    if 'None' in r[0]:
        no_exercise += int(r[1])

total = running + hiking + gym + biking + no_exercise

l = list()
l.append(['Running', running, '{percent:.1%}'.format(percent=running/total)])
l.append(['Hiking', hiking, '{percent:.1%}'.format(percent=hiking/total)])
l.append(['Gym', gym, '{percent:.1%}'.format(percent=gym/total)])
l.append(['Biking', biking, '{percent:.1%}'.format(percent=biking/total)])
l.append(['None', no_exercise, '{percent:.1%}'.format(percent=no_exercise/total)])

l = sorted(l, key=lambda r: r[1], reverse=True)
4

3 に答える 3

1

ここで使用できcollections.defaultdictます。'Type'dict は、任意の型に関連する値にアクセスできるため、ここではより優れたデータ構造ですO(1)

>>> from collections import defaultdict
>>> lis = [['Biking', '10'], ['Biking|Gym', '14'], ['Biking|Gym|Hiking', '9'],      ['Biking|Gym|Hiking|Running', '27']]
>>> total = 0
>>> dic  = defaultdict(lambda :[0])
for keys, val in lis:
    keys = keys.split('|')
    val = int(val)
    total += val*len(keys)
    for k in keys:
        dic[k][0] += val
...         
for k,v in dic.items():
    dic[k].append(format(v[0]/float(total), '.2%'))
...     
>>> dic
defaultdict(<function <lambda> at 0xb60e772c>,
{'Gym': [50, '28.90%'],
 'Biking': [60, '34.68%'],
 'Running': [27, '15.61%'],
 'Hiking': [36, '20.81%']})

値へのアクセス:

>>> dic['Biking']
[60, '34.68%']
>>> dic['Hiking']
[36, '20.81%']

もう 1 つの方法は、リストではなく値として dict を使用することです。

>>> dic = defaultdict(lambda :dict(val = 0))
>>> total = 0
for keys, val in lis:
    keys = keys.split('|')
    total += int(val)*len(keys)
    for k in keys:
        dic[k]['val'] += int(val)
...         
for k,v in dic.items():
    dic[k]['percentage'] = format(v['val']/float(total), '.2%')
...     
>>> dic
defaultdict(<function <lambda> at 0xb60e7b8c>, 
{'Gym': {'percentage': '28.90%', 'val': 50},
 'Biking': {'percentage': '34.68%', 'val': 60},
 'Running': {'percentage': '15.61%', 'val': 27},
 'Hiking': {'percentage': '20.81%', 'val': 36}})

値へのアクセス:

#Return percentage related to 'Gym'
>>> dic['Gym']['percentage']
'28.90%'
#return the total sum of 'Biking'
>>> dic['Biking']['val']
60
于 2013-08-06T16:57:32.670 に答える
1

おそらくこのようなものです(注:data.getのものを使用するのではなく、デフォルト値が0のcollections.defaultdictを使用できます..)?

sum=0
data={}
for extype, value in exercise_types_1:
   for item in extype.split('|'):
       sum += value
       data[item]=data.get(item,0)+value
l=[]
for k,v in data.iteritems():
   l.append([k,v, '{percent:.1%}'.format(percent=v/sum)])

l=sorted(l, key=lambda r: r[1], reverse=True)
于 2013-08-06T16:57:47.487 に答える