# { Dictionary Iteration and Comprehension. }

### Objectives

By the end of this chapter, you should be able to:

• Understand how to iterate through a dictionary
• Create dictionaries using dictionary comprehension
• Understand how to use data structures like `tuples` and `sets`

### Dictionary iteration

As with lists, we can use a `for in` loop to iterate through a dictionary. By default, the loop will iterate through the keys:

```d = dict(name = 'Elie', job = 'Instructor')

for k in d:
print(k)

# name
# job
```

If you want access to both the keys and the values, call `items` on the dictionary and iterate through the result:

```d = dict(name = 'Elie', job = 'Instructor')

for key, value in d.items():
print(f"{key}:{value}"

# name:Elie
# job:Instructor
```

### Dictionary comprehension

We can convert dictionaries into lists using list comprehension:

```d = {'a': 1, 'c': 3, 'e': 5}
[v for k,v in d.items()] # [1, 5, 3]
[k for k,v in d.items()] # ['a', 'e', 'c']
```

But we can also convert other data types into dictionaries using dictionary comprehension!

```str1 = "ABC"
str2 = "123"
{str1[i]: str2[i] for i in range(0,len(str1))} # {'A': '1', 'B': '2', 'C': '3'}
```

Whoaaa, what did we just do? Let's take a step back. We took each string at the character `i`, where `i` ranges over all whole numbers from 0 to 2. At each step, we're setting the character at index `i` in `str1` and setting it as a new key, with a value coming from the same index in `str2`.

Let's look at another dictionary comprehension example. This time, we'll take a list of numbers `[1,2,3,4]` and return a dictionary with the key as the number and the value as "odd" or "even". We can do some pretty cool stuff with dictionary comprehension here. Take a look!

```num_list = [1,2,3,4]
{ num:("even" if num % 2 == 0 else "odd") for num in num_list }
```

### Tuples

Tuples are another collection in Python, but they are immutable. This means that you can't reassign values in tuples like you can with lists. Because of this immutability, however, operations on tuples are faster than lists. If you're defining a collection of values that won't change (for instance, maybe all you're ever going to do with it is iterate through it), use a tuple instead of a list.

```x = (1,2,3)
3 in x # True
x[0] = "change me!" # TypeError: 'tuple' object does not support item assignment
```

Here are some common methods used on tuples (in alphabetical order):

#### `count`

Returns the number of times a value appears in a tuple:

```x = (1,2,3,3,3)
x.count(1) # 1
x.count(3) # 3
```

#### `index`

Returns the index at which a value is found in a tuple.

```t = (1,2,3,3,3)
t.index(1) # 0
t.index(5) # ValueError: tuple.index(x): x not in tuple
t.index(3) # 2 - only the first matching index is returned
```

### Sets

Sets do not have duplicate values, and elements in sets aren't ordered. You cannot access items in a set by index. Sets can be useful if you need to keep track of a collection of elements, but don't care about ordering. For example, if you wanted to check whether a certain number is prime, it would be helpful if you had a set of prime numbers to check against.

To test whether a value is a member of a set, use the `in` operator:

```# Sets cannot have duplictes
s = set({1,2,3,4,5,5,5}) # {1, 2, 3, 4, 5}

# Creating a new set
s = set({1,4,5})

# Creates a set with the same values as above
s = {4,1,5}

# True
4 in s

# False
8 in s
```

Here are some set methods (in alphabetical order):

#### `add`

Adds an element to a set. If the element is already in the set, the set doesn't change:

```s = set([1,2,3])
s # {1, 2, 3, 4}
s # {1, 2, 3, 4}
```

#### `clear`

Removes all the contents of the set:

```s = set([1,2,3])
s.clear()
s # set()
```

#### `copy`

Creates a copy of the set:

```s = set([1,2,3])
another_s = s.copy()
another_s # {1, 2, 3}
another_s is s # False
```

#### `difference`

Returns a new set containing all the elements that are in the first set but not in the set passed to `difference`:

```set1 = {1,2,3}
set2 = {2,3,4}
set1.difference(set2) # {1}
set2.difference(set1) # {4}
```

#### `intersection`

Returns a new set containing all the elements that are in both sets:

```set1 = {1,2,3}
set2 = {2,3,4}
set1.intersection(set2) # {2,3}
```

#### `symmetric_difference`

Returns a new set containing all the elements that are in exactly one of the sets:

```set1 = {1,2,3}
set2 = {2,3,4}
set1.symmetric_difference(set2) # {1,4}
```

#### `union`

Returns a new set containing all the elements that are in either set:

```set1 = {1,2,3}
set2 = {2,3,4}
set1.union(set2) # {1,2,3,4}
```

When you're ready, move on to Dictionary Exercises