# 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
{'Melissa Lewis': 'mlewis',
'Mark Watney': 'mwatney',
'Rick Martinez': 'rmartinez'}


Dict comprehension:

>>> DATA = {
...     'mlewis': 'Melissa Lewis',
...     'mwatney': 'Mark Watney',
...     'rmartinez': 'Rick Martinez',
... }
>>>
>>>
>>> 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

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


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