---
# System prepended metadata

title: 'Lec 1: Dictionaries'

---

# Dictionaries

---
title: Agenda
description:
duration: 300
card_type: cue_card
---

### Agenda

1. Motivation behind Dictionaries
2. Creating a Dictionary
3. Properties of Dictionaries
4. Iterating over Dictionaries
5. Sorting a Dictionary

---
title: Motivation behind Dictionaries
description:
duration: 1800
card_type: cue_card
---

### Motivation behind dictionaries - What do dictionaries signify in languages?

* Dictionaries in languages can be used to store meaning of different words.
* Python uses a syntax which is like a **key-value pair** with curly braces ```{ }``` around the elements.

<img src="https://d2beiqkhq929f0.cloudfront.net/public_assets/assets/000/040/078/original/dictionary_motivation.png?1689657748" width=600 height=200>

### Creating dictionaries in Python

* Curly Braces `{ }` around the values.
* Each value has two components - a **key** and a **value**.

Code:
``` python=
a = {
    "random": "something which is not well defined",
    "bizzare": "something which is unusual"
}

print(type(a))
```

> Output
```
<class 'dict'>
```

### Why dictionaries?

* Let's say you want to store the population of certain cities.
* You can do something like this -

Code:
``` python=
city_wise_data = {
    "Delhi": 450,
    "Mumbai": 400,
    "Bengaluru": 325
}
```

* But why not just use nested tuples?

Code:
``` python=
city_wise_data_tup = [("Delhi", 450), ("Mumbai", 400), ("Bengaluru", 325)]
```

* To access a list, we have to use indexing.
* For that, we need to remember the order in which we kept all the elements.

Code:
``` python
city_wise_data_tup[1]
```

> Output:
```
('Mumbai', 400)
```

* Dictionaries are **not ordered** or **subscriptable**.
* You access a value directly by using its **key**.

Code:
``` python=
city_wise_data["Bengaluru"]
```

> Output
```
325
```

---
title: Properties of a dictionary
description:
duration: 1800
card_type: cue_card
---

### Updating a dictionary

``` python=
a = {
    "Delhi": 450,
    "Mumbai": 400,
    "Bengaluru": 325
}

Code:
```python=
a["Delhi"] = 500

# The value is updated
a
```

> Output
```
{'Delhi': 500, 'Mumbai': 400, 'Bengaluru': 325}
```

Code:
``` python=
a["New Delhi"] = 350

# Creates a new key
a
```

> Output
```
{'Delhi': 500, 'Mumbai': 400, 'Bengaluru': 325, 'New Delhi': 350}
```

#### We can also use the ```.update()``` method to update the values of a dictionary.

Code:
``` python=
avenger = {
    "name": "Thor",
    "age": 1500,
    "weapon": "mjolnir"
}

# Old keys will be updated
# New keys will be added

avenger.update(
    {"name": "Thor Odinson",
     "weapon": ["mjonir", "stormbreaker"],
     "strongest": True}
)

avenger
```

> Output
```
{'name': 'Thor Odinson',
 'age': 1500,
 'weapon': ['mjonir', 'stormbreaker'],
 'strongest': True}
```

### Another way of accessing values of a dictionary

Code:
``` python=
random = {
    "a": 1,
    "b": 2,
    "c": 3
}

result = random.get("a")
print(result)
```

> Output
```
1
```

Code:
```python=
random["d"]
```

> Output
```
    ---------------------------------------------------------------------------
    KeyError                                  Traceback (most recent call last)
    <ipython-input-19-5d644a66c093> in <module>
          1 # Keyerror
    ----> 2 random["d"]

    KeyError: 'd'
```

Code:
``` python=
result = random.get("d")
print(result)
```

> Output
```
None
```

### How do we remove a key?

Code:
``` python=
random.pop("b")

```

> Output
```
2
```

Code:
``` python=
random
```

> Output
```
    {'a': 1, 'c': 3}
```

#### We need at least 1 argument when using ```.pop()``` on Dictionaries.

Code:
``` python=
random.pop() 
```

>Output:
```
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-27-2fd5921fdf48> in <module>
          1 # Throws an erorr
    ----> 2 random.pop()

    TypeError: pop expected at least 1 argument, got 0
```

---
title: Break & Doubt Resolution
description:
duration: 600
card_type: cue_card
---

### Break & Doubt Resolution

`Instructor Note:`
* Kindly take this time (up to 5-10 mins) to give a short break to the learners.
* Meanwhile, you can ask the them to share their doubts (if any) regarding the topics covered so far.

---
title: Iterating over dictionaries
description:
duration: 1800
card_type: cue_card
---

### Iterating over dictionaries

Code:
``` python=
a = {'name': 'Thor Odinson',
     'age': 1500,
     'weapon': ['mjonir', 'stormbreaker'],
     'strongest': True}
```

* The iterable gets all the keys as values.

Code:
``` python=
for i in a:
    print(i)
```

> Output
```
name
age
weapon
strongest
```

* To get the values we can do something as follows:

Code:
``` python=
for i in a:
    print(a[i])
```

> Output
```
Thor Odinson
1500
['mjonir', 'stormbreaker']
True
```

Code:
``` python=
for i in a:
    print(f"{i} -> {a[i]}")
```

> Output
```
name -> Thor Odinson
age -> 1500
weapon -> ['mjonir', 'stormbreaker']
strongest -> True
```

#### The ```.keys()``` method can be used to get a list of all the keys in a dictionary.

Code:
```python=
a.keys()
```

> Output
```
dict_keys(['name', 'age', 'weapon', 'strongest'])
```

#### The ```.values()``` method can be used to get a list of all the values in a dictionary.

Code:
``` python=
a.values()
```

> Output
```
dict_values(['Thor Odinson', 1500, ['mjonir', 'stormbreaker'], True])
```

#### The ```.items()``` method can be used to get a list of all the key-value pairs in a dictionary.

Code:
``` python=
a.items()
```

> Output
```
dict_items([('name', 'Thor Odinson'), ('age', 1500), ('weapon', ['mjonir', 'stormbreaker']), ('strongest', True)])
```

Code:
``` python=
for key, value in a.items():
    print(f"{key} -> {value}")
```

> Output
```
name -> Thor Odinson
age -> 1500
weapon -> ['mjonir', 'stormbreaker']
strongest -> True
```

---
title: How do we check if a key exists within a dictionary?
description:
duration: 300
card_type: cue_card
---

### How do we check if a key exists within a dictionary?

* We can simply use the `in` membership operator to achieve this.

Code:
``` python
"strongest" in a.keys()
```

> Output
```
True
```

Code:
``` python
"asdasd" in a.keys()
```

> Output
```
False
```

---
title: Can we have object of any datatype as a key in a dictionary?
description:
duration: 600
card_type: cue_card
---

### Can we have object of any datatype as a key in a dictionary?

* While discussing sets, we talked about how we cannot have **sets**, **dictionaries** and **lists** as elements of sets because they are **mutable**.

* This is the exact same case with dictionaries.
  * **Values** - Can store any data structure or any data type.
  * **Keys** - Lists, Sets and Dictionaries are not allowed.

Code:
``` python=
# Allowed
random = {
    "key1": [45, 56, 78],
    "key2": {
        "key3": (1, 2, 3)
    },
    45: "value3",
    56.78: "678",
    (1,2,3): "random value"
}
```

Code:
``` python=
# Not allowed
random = {
    "key1": [45, 56, 78],
    "key2": {
        "key3": (1, 2, 3)
    },
    45: "value3",
    56.78: "678",
    [1,2,3]: "random value"
}

```
> Output
```
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-41-a5e17c96aade> in <module>
          1 # Not allowed
    ----> 2 random = {
          3     "key1": [45, 56, 78],
          4     "key2": {
          5         "key3": (1, 2, 3)

    TypeError: unhashable type: 'list'
```

---
title: How to sort a dictionary?
description:
duration: 900
card_type: cue_card
---

Code:
```python=
my_dict = {'banana': 3, 'apple': 2, 'orange': 5, 'grape': 1}
print(my_dict)
```

> Output
```
{'banana': 3, 'apple': 2, 'orange': 5, 'grape': 1}
```

#### Sort the dictionary by keys -

Code:
```python=
sorted_dict_keys = dict(sorted(my_dict.items()))
print("Sorted by keys:", sorted_dict_keys)
```

> Output
```
Sorted by keys: {'apple': 2, 'banana': 3, 'grape': 1, 'orange': 5}
```

**Explanation:**

* `my_dict.items()`: It returns a list of tuples, where each tuple contains a key-value pair from the dictionary `my_dict`. 
  * For the given example, it would be `[('banana', 3), ('apple', 2), ('orange', 5), ('grape', 1)]`.

* `sorted()`: It sorts the list of tuples obtained from `my_dict.items()`. 
  * By default, it sorts based on the keys of the dictionary. 
  * Since the keys are strings, they will be sorted alphabetically.

* `dict()`: It creates a new dictionary from the sorted list of tuples.
  * So, when we run the code, `sorted_dict_keys` will be `{'apple': 2, 'banana': 3, 'grape': 1, 'orange': 5}`
 
#### Sort the dictionary by values -

Code:
```python=
sorted_dict_values = dict(sorted(my_dict.items(), key=lambda item: item[1]))
print("Sorted by values:", sorted_dict_values)
```

> Output
```
Sorted by values: {'grape': 1, 'apple': 2, 'banana': 3, 'orange': 5}
```

**Explanation:**

* `my_dict.items()`: It returns a list of tuples, where each tuple contains a key-value pair from the dictionary `my_dict`. 
  * For the given example, it would be `[('banana', 3), ('apple', 2), ('orange', 5), ('grape', 1)]`.

* `sorted()`: It sorts the list of tuples obtained from `my_dict.items()` based on a custom key. 
  * In this case, the custom key is a lambda function: `lambda item: item[1]`. 
  * This lambda function extracts the **second element (index 1)** from each tuple i.e. the values of the dictionary.

* `dict()`: It creates a new dictionary from the sorted list of tuples.
  * So, when we run the code, `sorted_dict_values` will be `{'grape': 1, 'apple': 2, 'banana': 3, 'orange': 5}`
  
---
title: Question - Creating a dictionary
description:
duration: 600
card_type: cue_card
---

### Question

* Take a string as input.
* Create a dictionary according to the following criteria :-
    * There will be one key-value pair for each unique character.
    * Key will be the character name.
    * Value will be the count of the character inside the string.

**Example Input:**
```
rrsssstttt
```

**Example Output:**
```
{
    "r": 2,
    "s": 3,
    "t": 4
}
```

Code:
```python=
string = "this is a random string with various characters"

result = {}
for i in set(string):
    result[i] = string.count(i)
result
```

> Output
```
{'c': 2,
 'd': 1,
 'h': 3,
 ' ': 7,
 'a': 5,
 'i': 5,
 'o': 2,
 'n': 2,
 'm': 1,
 'u': 1,
 'g': 1,
 's': 5,
 't': 4,
 'e': 1,
 'w': 1,
 'r': 5,
 'v': 1}
```

---
title: Practice Coding Question(s)
description: 
duration: 600
card_type: cue_card
---

### Practice Coding Question(s)

You can pick the following question and solve it during the lecture itself.

This will help the learners to get familiar with the problem solving process and motivate them to solve the assignments.

<span style="background-color: red;">Make sure to start the doubt session before you start solving the question.</span>

Q. https://www.scaler.com/hire/test/problem/96365/
