## Resources

See Sorting guide in the Python 3 docs.

## Iterables

### Sorted function

Using `sorted` built-in function to create a new list which is sorted. You can use it on a `list`, `tuple` or `set` but you always get a `list`.

On a list:

``````sorted([5, 2, 3, 1, 4])
# [1, 2, 3, 4, 5]
``````

On a tuple:

``````>>> sorted (( 1,5, 3))
[1, 3, 5]
``````

On a set:

``````>>> sorted({ 1 , 5, 3})
[1, 3, 5]
``````

Some more practical `list` examples.

Here we keep both lists.

``````my_strings = ["abc", "xyz", "def"]

my_sorted_strings = sorted(my_strings)
my_sorted_strings
# ['abc', 'def', 'xyz']
``````

Here we overwrite the original list.

``````my_strings = ["abc", "xyz", "def"]

my_strings = sorted(my_strings)
my_strings
# ['abc', 'def', 'xyz']
``````

Neatly with a `for` loop:

``````my_strings = ["abc", "xyz", "def"]

for s in sorted(my_strings):
print(s)
``````

### Sort method

Use `list.sort` method to modify in place. Only available on the `list` type.

``````a = [5, 2, 3, 1, 4]
a.sort()
a
# [1, 2, 3, 4, 5]
``````
``````my_strings = ["abc", "xyz", "def"]

my_strings.sort()
my_strings
# ['abc', 'def', 'xyz']
``````

### List of dictionaries

If you try and apply `sorted`

## Dictionaries

Applying `sorted` on `dict` will sort and return its keys only.

``````my_dict = {1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'}
sorted(my_dict)
# [1, 2, 3, 4, 5]
``````

You can use `dict.item` to get a list of tuples (each with a key and value). If you sort that list, the key will be used first to sort on. If two items have the same key, then the value will also be used.

``````sorted(my_dict.items())
# [(1, 'D'), (2, 'B'), (3, 'B'), (4, 'E'), (5, 'A')]
``````

You could use that like this, unpacking the two values of the tuple pair as key and value pairs.

``````for k, v in sorted(my_dict.items()):
print(k, v)

# 1 D
# 2 B
# 3 B
# 4 E
# 5 A
``````

Or iterate over the sorted keys and get the value too. This can be used to get keys and values together though.

``````my_dict = {1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'}

for k in sorted(my_dict):
print(k, my_dict[k])

# 1 D
# 2 B
# 3 B
# 4 E
# 5 A
``````

## Sort functions

Specify a function for logic to sort by.,

### Key functions

This works with both `sorted` and `list.sort`.

Supply a function to apply.

You can reference an existing function if you like.

``````str.lower
``````

Or a Lambda anonymous function, such as to reference a class attribute or dictionary key or to compare a value numerically.

``````lambda x: x['name']
``````

Here we sort a `list` as if all the elements were lowercase, but we keep the original values without actually storing any value as lowercase.

``````my_list = "This is a test string from Andrew".split()

sorted(my_list, key=str.lower)
# ['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
``````

Sort a list of class instances by the age attribute:

``````class Student:

self.name = name
self.age = age

def __repr__(self):

student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('dave', 'B', 10),
]

sorted(student_objects, key=lambda student: student.age)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
``````

### Operator module functions

These are easier and faster than key functions from above.

``````from operator import itemgetter

sorted(student_objects, key=itemgetter(2))
# [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
``````

Or

``````from operator import attrgetter

sorted(student_objects, key=attrgetter('age'))
# [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
``````

The operator module functions allow multiple levels of sorting. For example, to sort by grade then by age:

``````sorted(student_objects, key=itemgetter(1, 2))
# [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
``````
``````sorted(student_objects, key=attrgetter('grade', 'age'))
# [('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]
``````

## Reverse

### Reverse function

This returns an iterator, so remember to use convert to a list or use in a `for` loop.

``````my_strings = ['abc', 'def', 'xyz']

reversed(my_strings)
# <list_reverseiterator object at 0x10f343a90>

list(reversed(my_strings))
# ['xyz', 'def', 'abc']
``````

### Reversed method

``````my_strings = ['abc', 'def', 'xyz']

my_strings.reversed()

my_strings
# ['xyz', 'def', 'abc']
``````