好的,所以我试图了解我认为应该是一件容易的事。我使用的是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语句的简单性。这似乎也是整体上最快的选择。然而,对于那些不喜欢进口的人来说,价值主义(或实际价值字典)选项似乎也是一个不错的选择。
答案 0 :(得分:2)
使用defaultdict
from collections import defaultdict
values = defaultdict(int)
for x, y in newlist:
values[x]+=y
编辑:只使用defaultdict(int),int已经是一个可调用的我没有想到这一点!
答案 1 :(得分: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())
答案 2 :(得分:1)
I'd use a 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})
答案 3 :(得分:0)
valuelist = {}
for (name, value) in newlist:
if name not in valuelist:
valuelist[name] = 0
valuelist[name] += value
print (valuelist)
{&#39; Paul&#39;:20,&#39; John&#39;:19,&#39; Mary&#39;:15}
答案 4 :(得分:0)
最快的方法可能涉及来自Counter
的{{1}}和来自collections
的{{1}}和chain
{/ 1}}:
repeat
哪个收益率:
itertools
该语句将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
(j
),以便将其作为repeat
的输入提供。