with modules
Using groupby from itertools you can group with a lambda by first sorting with that same lambda and then grouping. With a list comprehension you then group together all the groupings and filter out everything that is of length 1 to get rid of tuples that do not share values.
from itertools import groupby
tuples = [(1, 2, 2), (3, 1, 3), (1, 2, 4), (8, 9, 2), (12, 1, 2), (0, 1, 3)]
tuple_tail = lambda (first, mid, last): last
tuples.sort(key=tuple_tail)
print filter(lambda item: len(item) > 1, [list(group) for key, group in groupby(tuples, tuple_tail)])
without modules
So this one isn't the best solution but it's a solution. I defined some helper functions that
retrieves last of tuple
compares equality of two tuples
.
Then wrote a custom group function that searches for all elements that are equal by using filter
and then map
that across all elements to obtain a list with all possible groupings (group all). I couldn't think of a way of using a list comprehension without making a mess so I went with reduce
and wrote a function to remove elements that were duplicates and/or length of 1 (fn). This could surely be optimized if you used set
or maybe just a different approach in general. Hope this helps you find whatever that approach will be.
tuples = [(1, 2, 2), (3, 1, 3), (1, 2, 4), (8, 9, 2), (12, 1, 2), (0, 1, 3)]
# helper functions
tuple_tail = lambda (first, mid, last): last
is_tuples_equal = lambda tuple1, tuple2: tuple_tail(
tuple1) == tuple_tail(tuple2)
# groups by last (_,_,last)
group_by_last = lambda tuple: filter(
lambda item: is_tuples_equal(item, tuple), tuples)
# get all groupings
group_all = map(group_by_last, tuples)
# if group is not in list and not length of 1 insert into list
fn = lambda acc, val: acc if val in acc or len(val) == 1 else acc + [val]
print reduce(fn, group_all, [])
with list comprehension
If you create a dictionary and use the tuple_tail
values of each tuple as the key
and make the value
as the all the tuples that contain that key
as their tail. You can then use a list comprehension to accumulate the values of the dictionary and dis include elements of length less than 1.
tuples = [(1, 2, 2), (3, 1, 3), (1, 2, 4), (8, 9, 2), (12, 1, 2), (0, 1, 3)]
mydict = dict()
create = lambda tupl: mydict.update({tuple_tail(tupl): [tupl]})
update = lambda tupl: mydict[tuple_tail(tupl)].append(tupl)
tuple_tail = lambda (first, mid, last): last
populate = lambda tupl: update(tupl) if tuple_tail(tupl) in mydict else create(tupl)
map(populate, tuples)
print [tuple for tuple in mydict.values() if len(tuple) > 1]
end results
[[(1, 2, 2), (8, 9, 2), (12, 1, 2)], [(3, 1, 3), (0, 1, 3)]]