Arnaud Delobelle: > You don't want to silence TypeErrors that may arise from with key() when > x or y is not a Guard, as it could hide bugs in key(). So I would write > something like this: > > def equal_items(iter1, iter2, key=lambda x: x, _fill = object()): > for x, y in izip_longest(iter1, iter2, fillvalue=_fill): > if x is _fill or y is _fill or key(x) != key(y): > return False > return True > > (untested)
You are right, thank you. Darn exceptions. You are often able to find bugs in my code. Here is a new version then (this is designed to be usable in practice, that's why it's longer): from itertools import izip_longest def equal_iter(iter1, iter2, key=None): """ >>> equal_iter([1, 2], [1, 2, 3]) False >>> equal_iter([1, 2, 3], [1, 2, 3]) True >>> equal_iter([1, 2, 3], [1, -2, 3]) False >>> equal_iter([1, 2, 3], [1, -2, 3], abs) True >>> equal_iter([1, 2, 3], [1, -2, 4], abs) False >>> L1, L2 = ["hello", "HALLO"], ["hello", "hallo"] >>> equal_iter(L1, L2) False >>> equal_iter(L1, L2, str.lower) True >>> equal_iter(xrange(3), (i for i in xrange(3))) True >>> equal_iter([0, 1, 2], (i for i in xrange(3))) True >>> equal_iter([0, 1, 2, 3], (i for i in xrange(3))) False >>> equal_iter([-0, -1, -2], (i for i in xrange(3)), key=abs) True >>> equal_iter([-0, -1, -2, -3], (i for i in xrange(3)), key=abs) False >>> x = [] >>> equal_iter( (x for i in range(3)), (x for i in range(3)) ) True >>> equal_iter( (x for i in range(3)), (x for i in range(4)) ) False >>> equal_iter( (x for i in range(3)), (x for i in range(3)), key=id) True >>> equal_iter( (x for i in range(3)), (x for i in range(4)), key=id) False >>> equal_iter( (x for i in range(3)), (x for i in range(3)), key=lambda x:x) True >>> equal_iter( (x for i in range(3)), (x for i in range(4)), key=lambda x:x) False >>> # bug found by Arnaud Delobelle >>> def k(x): raise TypeError >>> equal_iter( (x for i in range(3)), (x for i in range(3)), key=k) Traceback (most recent call last): ... TypeError """ try: len_iter1 = len(iter1) len_iter2 = len(iter2) except TypeError: pass else: if len_iter1 != len_iter2: return False class Guard(object): pass guard = Guard() if key is None: for x, y in izip_longest(iter1, iter2, fillvalue=guard): if x != y: return False else: for x, y in izip_longest(iter1, iter2, fillvalue=guard): if x is guard or y is guard or key(x) != key(y): return False return True if __name__ == "__main__": import doctest doctest.testmod() print "Doctests finished.\n" Bye, bearophile -- http://mail.python.org/mailman/listinfo/python-list