self.assertEqual(sorted_list_difference([2], [1, 1]), ([2], [1]))
self.assertEqual(sorted_list_difference([1, 2], [1, 1]), ([2], []))
+ def test_sorted_list_difference_tail_deduplication(self):
+ # Tail deduplication when one list is exhausted before the other.
+ # These exercise the except-IndexError path in sorted_list_difference.
+ self.assertEqual(sorted_list_difference([], [0, 0]), ([], [0]))
+ self.assertEqual(sorted_list_difference([0, 0], []), ([0], []))
+ self.assertEqual(sorted_list_difference([], [1, 1, 2, 2]), ([], [1, 2]))
+ self.assertEqual(sorted_list_difference([1, 1, 2, 2], []), ([1, 2], []))
+ # One list exhausts mid-way, leaving duplicated tail in the other.
+ self.assertEqual(sorted_list_difference([1], [1, 2, 2, 3, 3]), ([], [2, 3]))
+ self.assertEqual(sorted_list_difference([1, 2, 2, 3, 3], [1]), ([2, 3], []))
+
+ def test_sorted_list_difference_strings(self):
+ self.assertEqual(
+ sorted_list_difference(['a', 'b'], ['b', 'c']),
+ (['a'], ['c']))
+ self.assertEqual(
+ sorted_list_difference([], ['a', 'a', 'b']),
+ ([], ['a', 'b']))
+ self.assertEqual(
+ sorted_list_difference(['a', 'a', 'b'], []),
+ (['a', 'b'], []))
+
+ def test_sorted_list_difference_unhashable(self):
+ self.assertEqual(
+ sorted_list_difference([[1], [2]], [[2], [3]]),
+ ([[1]], [[3]]))
+ self.assertEqual(
+ sorted_list_difference([], [[0], [0]]),
+ ([], [[0]]))
+ self.assertEqual(
+ sorted_list_difference([[0], [0]], []),
+ ([[0]], []))
+
def test_unorderable_list_difference(self):
self.assertEqual(unorderable_list_difference([], []), ([], []))
self.assertEqual(unorderable_list_difference([1, 2], []), ([2, 1], []))
def strclass(cls):
return "%s.%s" % (cls.__module__, cls.__qualname__)
+def _dedupe_sorted(lst):
+ """Remove consecutive duplicate elements from a sorted list."""
+ result = []
+ for item in lst:
+ if not result or result[-1] != item:
+ result.append(item)
+ return result
+
def sorted_list_difference(expected, actual):
"""Finds elements in only one or the other of two, sorted input lists.
while actual[j] == a:
j += 1
except IndexError:
- missing.extend(expected[i:])
- unexpected.extend(actual[j:])
+ missing.extend(_dedupe_sorted(expected[i:]))
+ unexpected.extend(_dedupe_sorted(actual[j:]))
break
return missing, unexpected