简体   繁体   中英

Python summing values in list if it exists in another list

I have a list and a set:

a_list = [['1', 2], ['2', 1], ['1', 1]]

b_list = {'1', '2'}

I'm looking to correspond the items in b_list and sum their values from a_list so that the output is:

[['1', 3], ['2', 1]]

What I've tried...

sum = 0

for i in a_list:
        for j in b_list:
            if i[0] in j:
                sum += i[1]
        print(j, sum)

But this is giving giving me an incorrect output.

Accumulate numbers using a dict, and then gather the results using a list comprehension:

>>> d = dict.fromkeys(b_list, 0)
>>> for k, n in a_list: 
...     if k in d: 
...         d[k] += n 
...
>>> [[k, n] for k, n in d.items()]
[['1', 3], ['2', 1]]

Use a dict for grouping:

d = {}
for k, v in a_list:
    d[k] = d.get(k, 0) + v
print([[k, d[k]] for k in b_list])

prints:

[['2', 1], ['1', 3]]

You are on the right track! All you have to do is flip the order of your loops. For every value in b_list , you want to sum up all matching values in a_list , so b_list should be the external loop and a_list the internal. Also note your sum variable should be inside the first loop as it is different for every value in b_list .

If you make this change your code works as expected:

a_list = [['1', 2], ['2', 1], ['1', 1]]

b_list = {'1', '2'}

for j in b_list:
    sum = 0
    for i in a_list:
        if i[0] == j:
            sum += i[1]
    print(j, sum)

will give your desired output:

('1', 3)
('2', 1)

EDIT : the above solution is a minimal fix to the code posted in the question, however there are more efficient solutions:

Similar to wim's answer, you could use a defaultdictionary , which in this case would be (slightly) more efficient than using the built-in dict class:

from collections import defaultdict
#
a_list = [['1', 2], ['2', 1], ['1', 1]]
b_list = {'1', '2'}

dict = defaultdict(int)

for key, val in a_list:
    if key in b_list:
        dict[key] += val

print([[key, dict[key]] for key in b_list])

** credit to coldspeed for the idea for this second solution.

In [1]: a_list = [['1', 2], ['2', 1], ['1', 1]]
   ...:
   ...: b_list = {'1', '2'}

In [2]: out = [[i, sum(j[1] for j in a_list if j[0] == i)] for i in b_list]

In [3]: out
Out[3]: [['1', 3], ['2', 1]]

You can use sum of list or you can directly call sum. Here is a time performance of both approach:

In [6]: %timeit [[i, sum(j[1] for j in a_list if j[0] == i)] for i in b_list]
1.31 µs ± 2.52 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [7]: %timeit [[i, sum([j[1] for j in a_list if j[0] == i])] for i in b_list]
1.2 µs ± 1.67 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

This returns sums only for items defined in find.

items = [['1', 2], ['2', 1], ['1', 1], ['3',1]]
find = {'1', '2'}
results = {}

for item in items:
    key = item[0]
    value = item[1]
    if key in find:
        results[key] = results.get(key,0) + value

[[key, value] for key, value in results.items()] 

Outputs [['2', 1], ['1', 3]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM