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

"""
* Assignment: Comprehension About Create
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 2 min

English:
    1. Define `result: dict` with:
       a. `key: int` integer from 1 to 5 (exclusive)
       b. `value: str` value for key squared (raised to the power of 2)
       c. example: `{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}`
    2. Non-functional requirements:
        a. Use list comprehension
        b. Use `range()` function
        c. Run doctests - all must succeed

Polish:
    1. Zdefiniuj `result: dict` z:
       a. `klucz: int` liczba całkowita od 0 do 5 (rozłącznie)
       b. `wartość: str` wartość dla klucza podniesiona do kwadratu
       c. przykład: `{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}`
    2. Non-functional requirements:
        a. Użyj list comprehension
        b. Użyj funkcji `range()`
        c. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * [... for ... in ...]
    * range(start,stop)
    * start is inclusive
    * stop is exclusive

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

    >>> assert type(result) is dict, \
    'Result should be a dict'
    >>> assert all(type(x) is int for x in result), \
    'Result should be a list of int'

    >>> result
    {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
"""

# `key: int` integer from 1 to 5 (exclusive)
# `value: str` value for key squared (raised to the power of 2)
# example: `{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}`
# type: dict[int,int]
result = ...

"""
* 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 = ...

"""
* Assignment: Comprehension Dict Months
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min

English:
    1. Convert `DATA` into `result: dict`:
        a. Keys: month number
        b. Values: month name
    2. Run doctests - all must succeed

Polish:
    1. Przekonwertuj `DATA` w `result: dict`:
        a. klucz: numer miesiąca
        b. wartość: nazwa miesiąca
    2. Uruchom doctesty - wszystkie muszą się powieść

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'}
"""

DATA = [
    (1, 'January'),
    (2, 'February'),
    (3, 'March'),
    (4, 'April'),
    (5, 'May'),
    (6, 'June'),
    (7, 'July'),
    (8, 'August'),
    (9, 'September'),
    (10, 'October'),
    (11, 'November'),
    (12, 'December'),
]

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

"""
* Assignment: Comprehension Dict ZeroPadded
* Type: class assignment
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min

English:
    1. Define `result: dict` with `DATA` converted into:
        a. Keys: month number
        b. Values: month name
    2. Month number must be two letter string (zero padded)
    3. Use dict comprehension
    4. Run doctests - all must succeed

Polish:
    1. Zdefiniuj `result: dict` z `DATA` przekonwertowanym w:
        a. klucz: numer miesiąca
        b. wartość: nazwa miesiąca
    2. Numer miesiąca ma być dwuznakowym stringiem (wypełnij zerem)
    3. Użyj rozwinięcia słownikowego
    4. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `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'}
"""

DATA = [
    (1, 'January'),
    (2, 'February'),
    (3, 'March'),
    (4, 'April'),
    (5, 'May'),
    (6, 'June'),
    (7, 'July'),
    (8, 'August'),
    (9, 'September'),
    (10, 'October'),
    (11, 'November'),
    (12, 'December'),
]

# Define `result: dict` with `DATA` converted into:
#  a. Keys: month number
#  b. Values: month name
# Month number must be two letter string (zero padded)
# Use dict comprehension
# type: dict[str,str]
result = ...