2017-03-08 57 views
2

好的,所以我试图让我的头脑在我认为应该是一件容易的事情。我正在使用Python3.4。在指定条件下总结子列表中包含的值

我有以下列表包含子列表(简体版):

newlist = [ ['John', 12],['Mary', 10],['Paul', 12],['Mary', 5],['Paul', 8],['John', 7] ] 

我想获得对应于每个唯一的名称中的所有值的总和。因此,在考虑到上述列表中的结果应该读的东西,如:

约翰 - 19

玛丽 - 15

保罗 - 20

什么是最快和/或最有效的方法来实现这一目标?我自己的努力

现在,我已经解决了我的问题,像这样(但说:我在寻找一个更有效的解决方案):

unique_names = [] 
for i in newlist: 
    if i[0] not in unique_names: 
     unique_names.append(i[0]) 

valuelist = [] 
for name in unique_names: 
    valuelist.append(name) 
    yet_another_list = [] 
    for i in newlist: 
     if name in i: 
      yet_another_list.append(i[1]) 
    valuelist.append(sum(yet_another_list)) 

编辑我测试了答案 -

好的,所以我得到了很多回应,thnx!为了记录,我通过为每个建议的解决方案创建单独的功能来测试它们。我使用start = time.perf_counter()end = time.perf_counter() - start来计算每个函数的响应时间。我在每个需要它们的函数中封装了导入。

我用于此测试的列表包含3985个项目/子列表。

结果从5个不同的运行(四舍五入至4位小数)其中:

my_own_solution:0.9800/0.9703/0.9873/1.0023/0.9540

defaultdict try:0.0014/0.0016/0.0014/0.0018/0.0014

counter try:0.0030/0.0026/0.0026/0.0027/0.0026

reduce_try:0.0155/0.0153/0.0151/0.0149/0.0174

ittertry:0.0242/0.0268/0.0239/0.0307/0.0259(失败的花车)

valuelisttry:0.0018/0.0018/0.0019/0.0020/0.0043

总之,我真正体会到了defaultdict语句的简单性。这似乎也是整体上最快的选择。然而,对于那些不喜欢进口的人来说,价值评估者(或实际价值字典)选项似乎也是一个不错的选择。

回答

2

使用defaultdict

from collections import defaultdict 

values = defaultdict(int) 

for x, y in newlist: 
    values[x]+=y 

编辑:只使用defaultdict(INT ),int已经是可调用的,我没有想到!

+0

'int'已经是可调用的了,所以不需要将它包装在'lambda'中。 – timgeb

+0

你应该做'defaultdict(int)'。 –

0
valuelist = {} 
for (name, value) in newlist: 
    if name not in valuelist: 
    valuelist[name] = 0 
    valuelist[name] += value 

print (valuelist) 

{ '保罗':20, '约翰':19, '玛丽':15}

1

您可以使用collections.Counter对象:如果你到一个衬垫

from collections import Counter 

c = Counter() 
for name, cnt in newlist: 
    c[name] += cnt 

print(c.items()) 
# [('Paul', 20), ('John', 19), ('Mary', 15)] 

(虽然不一定更有效或可读的),你可以使用functools.reduce并传递一个Counter作为初始化:

from functools import reduce 

c = reduce(lambda x, y: x.update({y[0]: y[1]}) or x, newlist, Counter()) 
1

我会使用defaultdict。

>>> from collections import defaultdict 
>>> newlist = [ ['John', 12],['Mary', 10],['Paul', 12],['Mary', 5],['Paul', 8],['John', 7] ] 
>>> d = defaultdict(int) 
>>> for name, score in newlist: 
...  d[name] += score 
... 
>>> d 
defaultdict(<class 'int'>, {'Mary': 15, 'John': 19, 'Paul': 20}) 
0

最快的方式或许会从itertools涉及从collectionschainrepeat一个Counter

from_it = chain.from_iterable 
c = Counter(from_it(repeat(i, j) for i,j in chain(newlist))) 

其中产量:

Counter({'John': 19, 'Mary': 15, 'Paul': 20}) 

声明从newlist解压每个列表与for i,j in chain(newlist)然后输入字符串i(例如John)以及其计数jrepeat,以便重复该次数。这个理解然后传递到chain.from_iterablefrom_it),所以它可以作为输入提供给Counter