Python The Easiest Way to Summarize a List Intersecting a List of Tuples

Say I have the following two lists of tuples

myList = [(1, 7), (3, 3), (5, 9)] otherList = [(2, 4), (3, 5), (5, 2), (7, 8)] returns => [(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)] 

I would like to create a merge operation that combines the two lists, checking for any intersections of the first element of the tuple, if there are intersections, add the second element of each corresponding set (merge two). After the operation, I would like to sort by the first element.

I also post this because I think this is a fairly common problem that has an obvious solution, but I feel that there can be very pythonic solutions to this question;)

+7
source share
4 answers

Use the dictionary for the result:

 result = {} for k, v in my_list + other_list: result[k] = result.get(k, 0) + v 

If you need a list of tuples, you can get it through result.items() . The resulting list will be in random order, but of course you can sort it if you want.

(Note that I renamed your lists to match Python style conventions.)

+14
source

Use defaultdict:

 from collections import defaultdict results_dict = defaultdict(int) results_dict.update(my_list) for a, b in other_list: results_dict[a] += b results = sorted(results_dict.items()) 

Note. When sorting sequences sorted sorted is sorted by the first element in the sequence. If the first elements match, then it compares the second element. You can give the sorted function to sort using the key keyword argument:

 results = sorted(results_dict.items(), key=lambda x: x[1]) #sort by the 2nd item 

or

 results = sorted(results_dict.items(), key=lambda x: abs(x[0])) #sort by absolute value 
+4
source

Method using itertools:

 >>> myList = [(1, 7), (3, 3), (5, 9)] >>> otherList = [(2, 4), (3, 5), (5, 2), (7, 8)] >>> import itertools >>> merged = [] >>> for k, g in itertools.groupby(sorted(myList + otherList), lambda e: e[0]): ... merged.append((k, sum(e[1] for e in g))) ... >>> merged [(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)] 

This first combines the two lists and sorts them. itertools.groupby returns the elements of the combined list, grouped by the first element of the tuple, so it simply sums them up and puts them in the combined list.

+1
source
 >>> [(k, sum(v for x,v in myList + otherList if k == x)) for k in dict(myList + otherList).keys()] [(1, 7), (2, 4), (3, 8), (5, 11), (7, 8)] >>> 

tested for both Python2.7 and 3.2
dict(myList + otherList).keys() returns iterability containing a set of keys for merged lists
sum(...) takes 'k' to loop through the combined list and adds up the elements tuple 'v', where k == x

... but an extra cycle adds extra overhead. Using the explicit vocabulary suggested by Sven Marnach avoids it.

0
source

All Articles