Given the lists

```
>>> a = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
>>> b = [4, 2, 6, 1, 5, 0, 3]
```

Predict and explain the output of the following statements:

(a) `[a[x] for x in b]`

(b) `[a[x] for x in sorted(b)]`

(c) `[a[b[x]] for x in b]`

(d) `[x for (y,x) in sorted(zip(b,a))]`

(a) Index the items of `a`

using the elements of `b`

:

```
>>> [a[x] for x in b]
['E', 'C', 'G', 'B', 'F', 'A', 'D']
```

(b) Index the items of `a`

using the sorted elements of `b`

. In this case, the returned list is just (a copy of) `a`

:

```
>>> [a[x] for x in sorted(b)]
['A', 'B', 'C', 'D', 'E', 'F', 'G']
```

(c) Index the items of `a`

using the elements of `b`

indexed at the elements of `b`

(!)

```
>>> [a[b[x]] for x in b]
['F', 'G', 'D', 'C', 'A', 'E', 'B']
```

(d) Associate each element of `b`

with the corresponding element of `a`

in a sequence of tuples: `[(4, 'A'), (2, 'B'), (6, 'C'), ...]`

which is then sorted — this method is used to return the elements of `a`

corresponding to the ordered elements of `b`

.

```
>>> [x for (y,x) in sorted(zip(b,a))]
['F', 'D', 'B', 'G', 'A', 'E', 'C']
```