1

有两个列表。一个是code_list,另一个是points

code_list= ['ab','ca','gc','ab','we','ca']
points = [30, 20, 40, 20, 10, -10]

这两个列表像这样相互连接: 'ab' = 30, 'ca'=20 , 'gc' = 40, 'ab'=20, 'we'=10, 'ca'=-10

从这两个列表中,如果有相同的元素,我想得到每个元素的总和。最后,我会得到一个最重要的元素。我希望得到一个简单的结果,如下所示:

'ab' has the biggest point: 50

你能给我一个你的帮助吗?

4

3 回答 3

4

您可以使用一个collections.Counter()实例:

>>> from collections import Counter
>>> code_list= ['ab','ca','gc','ab','we','ca']
>>> points = [30, 20, 40, 20, 10, -10]
>>> c = Counter()
>>> for key, val in zip(code_list, points):
...     c[key] += val
... 
>>> c.most_common(1)
[('ab', 50)]

zip()配对你的两个输入列表。

正是最后一个调用在Counter()这里有用,该.most_common()调用在max()内部仅用于一个项目,但使用大于 1 的参数heapq.nlargest(),并且没有参数或要求使用len(c)sorted()使用。

于 2013-05-13T14:42:46.643 回答
1

还有一种方式:

ans={}
for k,v in zip(code_list,points):
    ans.setdefault(k,[]).append(v)

print max(ans, key=lambda k:sum(ans[k]))  

这将创建一个键的映射,其中code_points包含一个关联值列表,如下所示:

{'ca': [20, -10], 'ab': [30, 20], 'gc': [40], 'we': [10]}

该行max(ans, key=lambda k:sum(ans[k]))采用该映射并将列表汇总在一起以获得最大值。

这是另一种方式:

ans={k:0 for k in set(code_list)}
for k,v in zip(code_list,points):
    ans[k]+=v

print max(ans, key=lambda k: ans[k])  

该行使用值为 0 的ans={k:0 for k in set(code_list)}每个唯一键创建一个字典。然后循环将它们全部相加。code_list

或者,如评论中所述,这可能更好:

ans=dict.fromkeys(code_list,0)
for k,v in zip(code_list,points):
    ans[k]+=v

print max(ans, key=lambda k: ans[k])  

由于有一些关于性能的讨论,这里是一个测试:

from __future__ import print_function     # will run on Py 2.7 or 3.X
import timeit
from collections import Counter
from collections import defaultdict

points = [30, 20, 40, 20, 10, -10]
code_list= ['ab','ca','gc','ab','we','ca']

o1='''\
c=Counter()
for key, val in zip(code_list, points):
    c[key] += val

ans=c.most_common(1)    
'''

o2='''\
ans=defaultdict(int)

for k,v in zip(code_list,points):
    ans[k]+=v

m=max(ans, key=lambda k:ans[k])
'''

o3='''\
ans={}
for k,v in zip(code_list,points):
    ans.setdefault(k,[]).append(v)

m=max(ans, key=lambda k:sum(ans[k]))    

'''

o4='''\
ans={k:0 for k in set(code_list)}
for k,v in zip(code_list,points):
    ans[k]+=v

m=max(ans, key=lambda k: ans[k])  
'''

o5='''\
ans=dict.fromkeys(code_list,0)
for k,v in zip(code_list,points):
    ans[k]+=v

m=max(ans, key=lambda k: ans[k])  
'''

o6='''\
ans={}
for k,v in zip(code_list,points):
    ans[k]=ans.get(k,0)+v

m=max(ans, key=lambda k: ans[k])  
'''

fmt='{:20}{:>8.4f} seconds'
print (fmt.format('Counter:',timeit.timeit(o1, setup='from __main__ import points, Counter, code_list')))
print (fmt.format('defaultdict:',timeit.timeit(o2, setup='from __main__ import points, defaultdict, code_list')))
print (fmt.format('setdefault:',timeit.timeit(o3,setup='from __main__ import points, code_list')))
print (fmt.format('dict comprehension:',timeit.timeit(o4,setup='from __main__ import points, code_list')))
print (fmt.format('fromkeys:',timeit.timeit(o5,setup='from __main__ import points, code_list')))
print (fmt.format('dict.get():',timeit.timeit(o6,setup='from __main__ import points, code_list')))

打印(在我的机器上使用 Python 3.3):

Counter:             13.0980 seconds
defaultdict:          4.8093 seconds
setdefault:           5.3016 seconds
dict comprehension:   3.8282 seconds
fromkeys:             3.3764 seconds
dict.get():           3.4785 seconds

这表明这Counter()很慢。最快的速度是 3 倍

于 2013-05-13T14:58:44.953 回答
1

还有另一种方法,使用collections.defaultdict

>>> di = collections.defaultdict(int)
>>> for k,v in zip(code_list, points):
    di[k] += v

>>> max(di, key=lambda x:di[x])
'ab'

defaultdict如果您出于某种原因不想使用,请执行以下操作:

>>> di = {}
>>> for k,v in zip(code_list, points):
    if k not in di:
        di[k] = 0
    # or as suggested by Martijn Pieters
    # di[k] = di.get(k, 0) + v
    di[k] += v
于 2013-05-13T14:50:53.207 回答