在指定条件下汇总子列表中包含的值

时间:2017-03-08 11:25:21

标签: python python-3.x

好的,所以我试图了解我认为应该是一件容易的事。我使用的是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语句的简单性。这似乎也是整体上最快的选择。然而,对于那些不喜欢进口的人来说,价值主义(或实际价值字典)选项似乎也是一个不错的选择。

5 个答案:

答案 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提供给{{为了使它重复那么多次。然后将此理解传递给Johnj),以便将其作为repeat的输入提供。