问题描述:

Let's say I have a list of:

`5 10 10 20 50 50 20`

(there are 4 distinguish numbers).

I want to convert them to:

`0 1 1 2 3 3 2`

(then convert back to the original form).

There are tons of ways to do that, but I am not sure what is the best and Pythonic way?

(a way is to generate a set, convert the set to a list, sort the list, then generate output by the sorted list, but I think it is not the best one)

The suggested answer by Delgan is O(n^2) due to the nested loops in `back`

. This solution is O(n).

An alternative solution is as follows:

```
lst = [5, 10, 10, 20, 50, 50, 20]
# Convert (and build reverse mapping)
mapping = {}
reverse_mapping = {}
conv = []
for i in lst:
v = mapping.setdefault(i, len(mapping))
reverse_mapping[v] = i
conv.append(v)
# Convert back
back = [reverse_mapping[v] for v in conv]
```

I think this is a good problem for make use of `collections.defaultdict()`

and `itertools.count()`

methods.

```
from itertools import count
from collections import defaultdict
c = count()
dct = defaultdict(lambda: next(c))
lst = [5, 10, 10, 20, 50, 50, 20]
conv = [dct[i] for i in lst]
# [0, 1, 1, 2, 3, 3, 2]
back = [k for c in conv for k, v in dct.items() if v == c]
# [5, 10, 10, 20, 50, 50, 20]
```