 ## Introduction

Sorting algorithms are an essential part of every programming language, as they allow us to organize data efficiently. Python has its sorting methods, the built-in function `sorted(...)` and the built-in method `list.sort(...)`. They allow us to sort various data types, such as a list of tuples.

In this article, we will explore lists, tuples, lambda functions, and sorting. We will then use our understanding of these concepts to sort a list of tuples in Python.

## Difference Between List and Tuple

List and tuples are two data types in Python that store sequences of other data types. More generally, they are sometimes called sequences or collections. They both seem similar but are fundamentally different. Objects in both lists and tuples ordered, which allows us to access data with an index. But, tuples use parentheses `(...)` to enclose the data, while lists use square brackets `[...]`.

Furthermore, Python lists are mutable, while Python tuples are not. This means that a list can be changed in various ways after it is created/defined. We can add elements to a list or change data in a list after it is created. However, tuples are immutable. After creating a tuple, you can only read the data from it, not change the elements it contains.

Here are some examples:

``````>>> x = [1, 2, 'a', 'b']
>>> print(x, x)
2 a

>>> x = 'new'
>>> print(x)
['new', 2, 'a', 'b']

>>> x.append(5.5)
>>> print(x)
['new', 2, 'a', 'b', 5.5]

``````

In this example, we have a list x, containing both integer and string elements. We are able to print values in the list by indexing the elements we want. Note the list can also be changed in various ways. We can assign new values directly to an existing list index with the assignment operator. The `list.append(...)` built-in method adds a new value to the end of a list. Here we append the float `5.5` to the end of the list. These types of changes can be made on lists, no problem.

Let’s look at another example using a tuple:

``````>>> y = (1, 2, 'a', 'b')
>>> print(y, y)
2 a

>>> y = 'new'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

>>> y.append(5.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'

``````

In this example, we first create a new tuple y, with the same contents as list x. We then use indexing to print two values from the tuple. However, if we try to assign a new value to a tuple index or append values to the tuple, we encounter an error because tuples are not mutable.

Python has two built-in functions `list(...)` and `tuple(...)`, which let us convert other data types into lists or tuples.

``````>>> list()
[]

>>> tuple()
()

>>> y = (1, 2, 'a', 'b')
>>> z = list(y)
>>> print(z)
[1, 2, 'a', 'b']

>>> a = tuple(z)
>>> print(a)
(1, 2, 'a', 'b')

``````

In the example above, calling the `list(...)` and `tuple(...)` functions with no arguments returns an empty list and tuple, respectively. We then create a tuple y. Calling `list(...)` with tuple y as an argument returns the tuple as a list. The same is true vice-versa, calling the `tuple(...)` function with a list as an argument returns a tuple.

## Understanding Lambda Functions in Python

The `key` argument in Python's sorting function can used with a lambda function. Briefly, we will briefly discuss lambda functions.

Lambda functions are small functions that can have numerous arguments but only contain one expression.

``````>>> lb_func = lambda x: x + 2
>>> lb_func
<function <lambda> at 0x7f900d306430>

>>> print(lb_func(2))
4
``````

Above is a basic example of a lambda function. We create a lambda function with the `lambda` keyword followed by arguments, in this case x, followed by a colon `:`, followed by an expression `x+2`. The name `lb_func` is simply a variable that refers to the lambda function you define. Finally, we can call the lambda function like any other function, and it will return the expression in the lambda function.

## sort(...) vs sorted(...)

We can sort lists in Python with the built-in method `list.sort(...)`, or the built-in function `sorted(...)`. Both ways sort the list in the same way and also use the same arguments. But, they return values differently.

`list.sort(...)` sorts the list in-place, which means it changes the original list and returns `None`. In contrast, `sorted()` returns a new list which contains the sorted items from the original list.

``````>>> x = [2, 5, 9, 3, 1, 4, 0]
>>> print(x.sort())
None
>>> print(x)
[0, 1, 2, 3, 4, 5, 9]
``````

In this example, the list x is sorted using `list.sort(...)` method, and it returns `None`. But, printing x again, we can see it is now sorted. Let’s look at how `sorted(...)` handles this:

``````>>> x = [2, 5, 9, 3, 1, 4, 0]
>>> print(sorted(x))
[0, 1, 2, 3, 4, 5, 9]
>>> print(x)
[2, 5, 9, 3, 1, 4, 0]
``````

Sorting x with `sorted(...)` returns a new sorted list. We can confirm this by printing x to see that it is unchanged. `sorted(...)` can be great when you want to sort a list, assign it to another variable and still have access to the original list.

## How Does Sorting Work in Python?

Now we'll discuss the sorting algorithms that Python uses under the hood.

## Timsort Algorithm is Used Behind the Scenes

Python’s `sorted(...)` and `list.sort(...)` use the TimSort sorting algorithm. This algorithm is based on Insertion and Merge Sort. TimSort divides lists into parts called runs. The runs are then sorted using Insertion Sort and ultimately merged with Merge Sort.

### Sorting various data types

Python can sort various data types, but sorting two different data types (e. g. integers and strings) produces an error. By default, integers are sorted by ordering them from least to greatest. Ordering strings tend to be more confusing since they include upper and lower case letters, digits, and special characters.

``````>>> c = ['Australia', 'china', 'England', 'america', 'France', 'Germany', 'Japan', '%', '0', '52']
>>> sorted(c)
['%', '0', '52', 'Australia', 'England', 'France', 'Germany', 'Japan', 'america', 'china']
``````

Above, a list `c` with different types of strings is sorted. Strings are sorted by the Unicode integer representing it.

``````>>> sorted(list(zip(c, list(map(lambda i: i, c)), list(map(lambda i: ord(i), c)))))
[('%', '%', 37),
('0', '0', 48),
('52', '5', 53),
('Australia', 'A', 65),
('England', 'E', 69),
('France', 'F', 70),
('Germany', 'G', 71),
('Japan', 'J', 74),
('america', 'a', 97),
('china', 'c', 99)]
>>>
``````

Here, ignore the code used and only focus on the output. We have a sorted list, with tuples each containing three values. The value from list `c`, its first character, and the Unicode value of that character (obtained using Python's built-in function `ord(...)`). We can see that the corresponding Unicode values are from least to greatest, which shows that it's used to sort the strings.

For more details, check out the Python Docs on sorting.

## Sorting List of Tuples

Understanding lists, tuples, sorting, and lambda functions will allow us to better understand how to sort a list of tuples. Let us look at a basic example.

Below we have two identical lists of tuples `tl_1` and `tl_2`, sorted with two different methods.

``````>>> tl_1 = [(5, 7, 9), (3, 0, 8), (0, 5, 3)]
>>> tl_2 = [(5, 7, 9), (3, 0, 8), (0, 5, 3)]
>>>
>>> sorted(tl_1)
[(0, 5, 3), (3, 0, 8), (5, 7, 9)]
>>> sorted(tl_2, key=lambda i: i)
[(0, 5, 3), (3, 0, 8), (5, 7, 9)]
``````

In the first method, I use `sorted(...)` on `tl_1`. But, in the second method, I use the `key` argument with a lambda function to use the first integer in the tuple to sort the list. In the lambda function, `i` is the value in the list (the tuple), and `i` represents the first value in the tuple. Both outputs being identical confirms that `sorted(...)` uses the first value in the tuple to sort, before moving on to the next value if there is a match.

We can use the same lambda function to sort by any index by changing `0` to another value:

``````>>> sorted(tl_1, key=lambda i: i)
[(3, 0, 8), (0, 5, 3), (5, 7, 9)]

>>> sorted(tl_1, key=lambda i: i)
[(0, 5, 3), (3, 0, 8), (5, 7, 9)]
``````

We can also sort lists of tuples where the values in the tuples are different data types:

``````>>> cn = [('Germany',120), ('France',110), ('England',40) , ('Japan',184), ('China',20)]
>>> sorted(cn)
[('China', 20), ('England', 40), ('France', 110), ('Germany', 120), ('Japan', 184)]
``````

But, the index value used to sort the list must be all the same data type.

``````>>> cn2 = [(120, 100, 'Germany'), ('France',110) , ('England',40) , ('Japan',184), ('China',20)]
>>>
>>> sorted(cn2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'str' and 'int'

>>> sorted(cn2, key=lambda i: i)
[('China', 20), ('England', 40), (120, 100, 'Germany'), ('France', 110), ('Japan', 184)]
``````

When sorting `cn2` an error is produced because the first values are not all strings. But, using the second value works because those values are all integers.

## Summary

In this article, we looked at the difference between lists and tuples. We briefly explained how lambda functions work. We learned the difference between Python’s `list.sort(...)` method and `sorted(...)` function. Then we took a deeper look at how sorting in Python works by learning about TimSort and sorting various data types. Finally, we used our understanding of these concepts to sort list of tuples in Python, in various ways.

## Next Steps

If you're interested in learning more about the basics of Python, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.