12.4. Comprehension Dict

12.4.1. Syntax

Short syntax:

>>> {x:None for x in range(0,5)}
{0: None, 1: None, 2: None, 3: None, 4: None}

Long syntax:

>>> dict((x,None) for x in range(0,5))
{0: None, 1: None, 2: None, 3: None, 4: None}

12.4.2. Example

>>> {x:x for x in range(0,5)}
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4}
>>> {x:None for x in range(0,5)}
{0: None, 1: None, 2: None, 3: None, 4: None}
>>> {None:x for x in range(0,5)}
{None: 4}

12.4.3. Dict Collision

Recap information about dict keys collision. Duplicating items are overridden by the latter:

>>> data = {
...     'commander': 'Mark Watney',
...     'commander': 'Melissa Lewis',
... }
>>>
>>> data
{'commander': 'Melissa Lewis'}

While generating dict with unique keys, there are no collisions:

>>> {x:None for x in range(0,5)}
{0: None, 1: None, 2: None, 3: None, 4: None}

Although when generating dict with constant key, it will be overridden by the last one:

>>> {None:x for x in range(0,5)}
{None: 4}

12.4.4. Modify Key/Values

Modify keys:

>>> {x+10:x for x in range(0,5)}
{10: 0, 11: 1, 12: 2, 13: 3, 14: 4}

Modify values:

>>> {x:x+10 for x in range(0,5)}
{0: 10, 1: 11, 2: 12, 3: 13, 4: 14}

Modify keys and values:

>>> {x+10:x+10 for x in range(0,5)}
{10: 10, 11: 11, 12: 12, 13: 13, 14: 14}

12.4.5. Dict Reversal

Swap dict keys with values.

Algorithm:

>>> DATA = {
...     'mlewis': 'Melissa Lewis',
...     'mwatney': 'Mark Watney',
...     'rmartinez': 'Rick Martinez',
... }
>>>
>>>
>>> result = {}
>>>
>>> for username, user in DATA.items():
...     result[user] = username
>>>
>>> result  
{'Melissa Lewis': 'mlewis',
 'Mark Watney': 'mwatney',
 'Rick Martinez': 'rmartinez'}

Dict comprehension:

>>> DATA = {
...     'mlewis': 'Melissa Lewis',
...     'mwatney': 'Mark Watney',
...     'rmartinez': 'Rick Martinez',
... }
>>>
>>>
>>> result = {user:username for username,user in DATA.items()}
>>> result = {v:k for k,v in DATA.items()}
>>>
>>> result  
{'Melissa Lewis': 'mlewis',
 'Mark Watney': 'mwatney',
 'Rick Martinez': 'rmartinez'}

12.4.6. Dict Reversal Collision

>>> DATA = {'a': 1, 'b': 2}
>>>
>>>
>>> {v:k for k,v in DATA.items()}
{1: 'a', 2: 'b'}

Value collision while reversing dict:

>>> DATA = {'a': 1, 'b': 2, 'c': 2}
>>>
>>> {v:k for k,v in DATA.items()}
{1: 'a', 2: 'c'}

12.4.7. Use Case - 0x01

  • Even or Odd

>>> result = {}
>>>
>>> for x in range(0,5):
...     is_even = (x % 2 == 0)
...     result.update({x: is_even})
>>>
>>> print(result)
{0: True, 1: False, 2: True, 3: False, 4: True}
>>> {x: (x%2==0) for x in range(0,5)}
{0: True, 1: False, 2: True, 3: False, 4: True}

12.4.8. Assignments

Code 12.4. Solution
# TODO: Usunąć z zadania enumerate, na podstawach go nie ma
"""
* Assignment: Comprehension Dict Months
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min

English:
    1. Use dict comprehension and enumerate
    2. Convert `MONTH` into dict:
        a. Keys: month number
        b. Values: month name
    3. Run doctests - all must succeed

Polish:
    1. Użyj rozwinięcia słownikowego i enumeracji
    2. Przekonwertuj `MONTH` w słownik:
        a. klucz: numer miesiąca
        b. wartość: nazwa miesiąca
    3. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `enumerate()`

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from pprint import pprint

    >>> type(result)
    <class 'dict'>
    >>> 0 not in result
    True
    >>> 13 not in result
    True
    >>> result[1] == 'January'
    True

    >>> assert all(type(x) is int for x in result.keys())
    >>> assert all(type(x) is str for x in result.values())

    >>> pprint(result)
    {1: 'January',
     2: 'February',
     3: 'March',
     4: 'April',
     5: 'May',
     6: 'June',
     7: 'July',
     8: 'August',
     9: 'September',
     10: 'October',
     11: 'November',
     12: 'December'}
"""

MONTHS = [
    'January', 'February', 'March',
    'April', 'May', 'June',
    'July', 'August', 'September',
    'October', 'November', 'December',
]

# number and month name
# type: dict[str,str]
result = ...

Code 12.5. Solution
# TODO: Usunąć z zadania enumerate, na podstawach go nie ma
"""
* Assignment: Comprehension Dict ZeroPadded
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min

English:
    1. Use dict comprehension and enumerate
    2. Convert `MONTH` into `result: dict[str,str]`:
        a. Keys: month number
        b. Values: month name
    3. Month number must be two letter string
       (zero padded) - `f'{number:02}'`
    4. Run doctests - all must succeed

Polish:
    1. Użyj rozwinięcia słownikowego i enumeracji
    2. Przekonwertuj `MONTH` w `result: dict[str,str]`:
        a. klucz: numer miesiąca
        b. wartość: nazwa miesiąca
    3. Numer miesiąca ma być dwuznakowym stringiem
       (wypełnij zerem) - `f'{number:02}'`
    4. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `enumerate()`
    * `f'{number:02}'`

Tests:
    >>> import sys; sys.tracebacklimit = 0
    >>> from pprint import pprint

    >>> type(result)
    <class 'dict'>
    >>> '00' not in result
    True
    >>> '13' not in result
    True
    >>> result['01'] == 'January'
    True

    >>> assert all(type(x) is str for x in result.keys())
    >>> assert all(type(x) is str for x in result.values())
    >>> assert all(len(x) == 2 for x in result.keys())

    >>> pprint(result)
    {'01': 'January',
     '02': 'February',
     '03': 'March',
     '04': 'April',
     '05': 'May',
     '06': 'June',
     '07': 'July',
     '08': 'August',
     '09': 'September',
     '10': 'October',
     '11': 'November',
     '12': 'December'}
"""

MONTHS = [
    'January', 'February', 'March',
    'April', 'May', 'June',
    'July', 'August', 'September',
    'October', 'November', 'December',
]

# With zero-padded number and month name
# type: dict[str,str]
result = ...

Code 12.6. Solution
"""
* Assignment: Comprehension Dict Reverse
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min

English:
    1. Use dict comprehension to reverse dict:
       that is: change keys for values and values for keys
    2. Run doctests - all must succeed

Polish:
    1. Użyj rozwinięcia słownikowego do odwócenia słownika:
       to jest: zamień klucze z wartościami i wartości z kluczami
    2. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `dict.items()`

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert type(result) is dict
    >>> assert all(type(x) is str for x in result.keys())
    >>> assert all(type(x) is int for x in result.values())
    >>> assert len(result.keys()) == 3

    >>> assert 'virginica' in result.keys()
    >>> assert 'setosa' in result.keys()
    >>> assert 'versicolor' in result.keys()

    >>> assert 0 in result.values()
    >>> assert 1 in result.values()
    >>> assert 2 in result.values()

    >>> result
    {'virginica': 0, 'setosa': 1, 'versicolor': 2}
"""

DATA = {
    0: 'virginica',
    1: 'setosa',
    2: 'versicolor',
}

# type: dict[str,int]
result = ...