def duplicates(*iterables, **kwargs):
key = kwargs.pop('<STR_LIT:key>', lambda x: x)<EOL>assert not kwargs<EOL>zipped = more_itertools.collate(*iterables, key=key)<EOL>grouped = itertools.groupby(zipped, key=key)<EOL>groups = (<EOL>tuple(g)<EOL>for k, g in grouped<EOL>)<EOL>def has_dupes(group):<EOL><INDENT>return len(group) > <NUM_LIT:1><EOL><DEDENT>return filter(has_dupes, groups)<EOL>
Yield duplicate items from any number of sorted iterables of items

>>> items_a = [1, 2, 3]
>>> items_b = [0, 3, 4, 5, 6]
>>> list(duplicates(items_a, items_b))
[(3, 3)]

It won't behave as you expect if the iterables aren't ordered

>>> items_b.append(1)
>>> list(duplicates(items_a, items_b))
[(3, 3)]
>>> list(duplicates(items_a, sorted(items_b)))
[(1, 1), (3, 3)]

This function is most interesting when it's operating on a key
of more complex objects.

>>> items_a = [dict(email='joe@example.com', id=1)]
>>> items_b = [dict(email='joe@example.com', id=2), dict(email='other')]
>>> dupe, = duplicates(items_a, items_b, key=operator.itemgetter('email'))
>>> dupe[0]['email'] == dupe[1]['email'] == 'joe@example.com'
True
>>> dupe[0]['id']
1
>>> dupe[1]['id']
2