``````

In [4]:

def compact(iterable):
"""Return new iterable with adjacent duplicate values removed."""
current = object()

for e in iterable:
if e != current:
current = e
yield e

``````
``````

In [5]:

import unittest

class CompactTests(unittest.TestCase):

"""Tests for compact."""

def assertIterableEqual(self, iterable1, iterable2):
self.assertEqual(list(iterable1), list(iterable2))

def test_no_duplicates(self):
self.assertIterableEqual(compact([1, 2, 3]), [1, 2, 3])

self.assertIterableEqual(compact([1, 1, 2, 2, 3]), [1, 2, 3])

self.assertIterableEqual(compact([1, 2, 3, 1, 2]), [1, 2, 3, 1, 2])

self.assertIterableEqual(compact([1, 1, 1, 1, 1, 1]), [1])

def test_empty_values(self):
self.assertIterableEqual(compact([None, 0, "", []]), [None, 0, "", []])

def test_empty_list(self):
self.assertIterableEqual(compact([]), [])

# To test the Bonus part of this exercise, comment out the following line
# @unittest.expectedFailure
def test_accepts_iterator(self):
nums = (n**2 for n in [1, 2, 3])
self.assertIterableEqual(compact(nums), [1, 4, 9])

# To test the Bonus part of this exercise, comment out the following line
# @unittest.expectedFailure
def test_returns_iterator(self):
output = compact([1, 2, 3])
self.assertEqual(iter(output), iter(output))

if __name__ == "__main__":
unittest.main(argv=['first-arg-is-ignored'], exit=False)

``````
``````

........
----------------------------------------------------------------------
Ran 8 tests in 0.004s

OK

``````

# Key Takeaways

1. object() - This will give an unique object, which can used instead of None

## Another solution: Will not work for iterator objects passed as parameters

### Reason: the *items will consume the iterator

``````

In [28]:

def compact(items):
"""Return new iterable with adjacent duplicate values removed."""
for item, prev in zip(items, [object(), *items]):
if item != prev:
yield item

``````

### Note the neat trick of shifting the items by 1 and then using the zip function to compare elements of the iterable

``````

In [29]:

import unittest

class CompactTests(unittest.TestCase):

"""Tests for compact."""

def assertIterableEqual(self, iterable1, iterable2):
self.assertEqual(list(iterable1), list(iterable2))

def test_no_duplicates(self):
self.assertIterableEqual(compact([1, 2, 3]), [1, 2, 3])

self.assertIterableEqual(compact([1, 1, 2, 2, 3]), [1, 2, 3])

self.assertIterableEqual(compact([1, 2, 3, 1, 2]), [1, 2, 3, 1, 2])

self.assertIterableEqual(compact([1, 1, 1, 1, 1, 1]), [1])

def test_empty_values(self):
self.assertIterableEqual(compact([None, 0, "", []]), [None, 0, "", []])

def test_empty_list(self):
self.assertIterableEqual(compact([]), [])

# To test the Bonus part of this exercise, comment out the following line
@unittest.expectedFailure
def test_accepts_iterator(self):
nums = (n**2 for n in [1, 2, 3])
self.assertIterableEqual(compact(nums), [1, 4, 9])

# To test the Bonus part of this exercise, comment out the following line
# @unittest.expectedFailure
def test_returns_iterator(self):
output = compact([1, 2, 3])
self.assertEqual(iter(output), iter(output))

if __name__ == "__main__":
unittest.main(argv=['first-arg-is-ignored'], exit=False)

``````
``````

x.......
----------------------------------------------------------------------
Ran 8 tests in 0.004s

OK (expected failures=1)

``````
``````

In [ ]:

``````