Skip to main content

Different Ways of Sorting Data in a List - Python

Sorting Data in a List

List is a collection of data (of different data types), much like an array. Like any data structure or data set, data in the list doesn't necessarily be in any specific order. 

At times, depending on the use case we get to order the data in a specific sequence (Ascending, Descending or Reverse).

There are couple of methods and functions for sorting the data in a list, which can be used depending on the use case. 

  • sort() method 
  • sorted() function
  • reverse() method
  • reversed() function 
Let's have a look at each of these in detail. 

sort() method

Sort() method by default sorts the data in an ascending order. One important thing to remember about sort() method is that, it sorts the list in-place, meaning the list on which method is called would be sorted and the method would return None (no sorted list would be returned). 

Syntax

        list.sort(<key=None>, <reverse=False>)

The two parameters key and reverse mentioned in the syntax are optional. None and False are considered by default for key and reverse parameters respectively. 

If no parameters are passed to the sort method, list would be sorted in an ascending order by default. 

Let's have a look at an example. 

1

2

3

4

input_list = [4, 2, 5, 3, 1]

input_list.sort()

print(input_list) # [1, 2, 3, 4, 5]


This is the most common and straight forward example, where a list contains set of integers and using the sort() method modifies the list with the integers sorted in an ascending order. 

Before looking at the other optional parameters of the sort method, let's see what happens if the list contains data of other data type than integer. 

1

2

3

4

5

input_list = ["FOUR", "TWO", "FIVE", "THREE", "ONE"]

input_list.sort()

print(input_list)

# ['FIVE', 'FOUR', 'ONE', 'THREE', 'TWO']



A list with string data would sort fine i.e., data would be sorted in alphabetical order. 

So, how does the sort work if there is a mixed data types in a list. E.g.: both integer and string. 

1

2

3

input_list = [4, "TWO", 5, "THREE", 1]

input_list.sort()



Trying to sort a list which contains the data of different types would throw a TypeError. 

TypeError: '<' not supported between instances of 'str' and 'int'


So, need to be cautious when using the sort method on a list where the data types of the elements are unknown. 

Optional Parameter - reverse

Let's now explore the use of the optional parameter 'reverse' first and then see the importance of 'key'. 

As the name states, passing 'True' to the 'reverse' parameter would result in the output to be in the reverse order than the default i.e., Data in the list would be sorted in a descending order. 

Let's take a look at the same example as above, but with reverse parameter set to True.

1

2

3

4

input_list = [4, 2, 5, 3, 1]

input_list.sort(reverse=True)

print(input_list) # [5, 4, 3, 2, 1]



1

2

3

4

5

input_list = ["FOUR", "TWO", "FIVE", "THREE", "ONE"]

input_list.sort(reverse=True)

print(input_list)

# ['TWO', 'THREE', 'ONE', 'FOUR', 'FIVE']



In both the cases, the list is sorted in a descending order. TypeError would still remain when data of different types is present in the list. 

Optional Parameter - key

Optional parameter 'key' accepts a function as a parameter and the default value is None. This parameter becomes extremely helpful where there is a nested lists (or tuples as elements). 

When a function is passed to the 'key' parameter, function is applied to each element and sorts the list based on the value returned. 

This can be better understood with a simple example. Let's look at the below without passing the 'key' first. 

1

2

3

4

5

input_list = [(5, 5), (20, 2), (15, 3), (35, 1), (25, 4)]

input_list.sort()

print(input_list)

# [(5, 5), (15, 3), (20, 2), (25, 4), (35, 1)]



In the above example, a list contains all tuples, with each tuple containing two elements. When a sort() method is called, data would be sorted based on the first element of the tuples embedded by default. 

By passing the function that returns the value of the element in the second element (i.e., index - 1), data would be sorted based the corresponding element. 

1

2

3

4

5

input_list = [(5, 5), (20, 2), (15, 3), (35, 1), (25, 4)]

input_list.sort(key=lambda x:x[1])

print(input_list) 

# [(35, 1), (20, 2), (15, 3), (25, 4), (5, 5)]



In the above example, we are passing the lambda function that returns the element at the index - 1 for the list. This function is called for every element of the list and sorts the list in ascending order of the corresponding element. 

Both the optional parameters key and reverse can be used at the same time as per the requirement. 

1

2

3

4

5

input_list = [(5, 5), (20, 2), (15, 3), (35, 1), (25, 4)]

input_list.sort(key=lambda x:x[1], reverse=True)

print(input_list)

# [(5, 5), (25, 4), (15, 3), (20, 2), (35, 1)]



Like we have seen earlier, if the data is of different data types, if the list contains a combination of lists and tuples as elements, TypeError would be thrown. To note, this would only happen with the default value for the 'key' parameter. 

1

2

3

4

input_list = [(5, 5), (20, 2), (15, 3), (35, 1), [25, 4]]

input_list.sort()

print(input_list)


TypeError: '<' not supported between instances of 'list' and 'tuple'


We are trying to compare a list with tuple with list, which is not supported. This can be partially avoided with the use of 'key' function. 

1

2

3

4

5

input_list = [(5, 5), (20, 2), (15, 3), (35, 1), [25, 4]]

input_list.sort(key=lambda x:x[1])

print(input_list)

# [(35, 1), (20, 2), (15, 3), [25, 4], (5, 5)]



No error occurs in this scenario, because the function passed for the key parameter retrieves the element in index '1' and compares. However, if the contents of the nested list or tuple are different for the index specified in the key function, the error would still occur. 

1


2

3

4

input_list = [(5, 5), (20, 2), (15, 3), (35, 1), [25, "FOUR"]]

input_list.sort(key=lambda x:x[1])

print(input_list)



TypeError: '<' not supported between instances of 'str' and 'int'


One final error scenario, before we move on to the other functions/methods is if the number of elements of the embedded list/tuples is not same, then the index specified in the key function must be not greater than the tuple/list that contains the minimum number of elements. 

If not, index out of range error would occur. 

1


2

3

4

input_list = [(5, 5), (20, 2, 3), (15, 3), (35, 1, 1), (25, 4)]

input_list.sort(key=lambda x:x[2])

print(input_list)



Tuples (5, 5), (15, 3) and (25, 4) only contain 2 elements and passing '2' as index in lambda function would result in error (as this function needs to be called for every element of a list on which sort() method is called). 

IndexError: tuple index out of range


Passing the lambda function (key=lambda x:x[1]) with index as '1' would not result in an error. 

Most of these scenarios for sort() method are also applicable for the sorted() function and not detailing again.

sorted() function

Like sort() method, sorted() function also sorts the data in an ascending order by default. 

Primarily there are couple of differences between the sort() method and sorted() function. 
  • sorted() function accepts an iterable as an input and returns the sorted list. It does not modify the list passed, whereas sort() method modifies the list in-place. 
  • sorted() function accepts any iterable (List, Tuple or Set) and returns the sorted list, where as the sort() method can only be used on Lists. 

Syntax

        list = sorted(<iterable>, <key=None>, <reverse=False>)

Let's have a look at an example with by passing a list and a tuple having same data with the default parameters and see. 

1

2

3

4

5

6

7

8

input_list = [4, 2, 5, 3, 1]

output_list = sorted(input_list)

print(input_list) # [4, 2, 5, 3, 1]

print(output_list) # [1, 2, 3, 4, 5]


input_tuple = (4, 2, 5, 3, 1)

output_list = sorted(input_tuple)

print(input_tuple) # (4, 2, 5, 3, 1)

print(output_list) # [1, 2, 3, 4, 5]



In the above example, 
  • Line - 2: We are passing a list to the sorted() function, with default values for both key and reverse parameters. sorted() function returns a list that is sorted in ascending order. And, no change to the input list.
  • Line - 6: We are passing a tuple to the sorted() function, with default values for the remaining two parameters. sorted() function returns a list that is sorted in ascending order. 
Like we have seen for the sort() method, data in the list/tuple that we are passing to sorted() function should contain data of a single data type. Otherwise, TypeError would be thrown. 

Optional Parameter - reverse

Let's now explore the use of the optional parameter 'reverse' first, functionality of this parameter would remain same as above. Passing 'True' to the 'reverse' parameter would result in the output to be in the reverse order than the default i.e., Data in the list would be sorted in a descending order. 

Let's take a look at the same example as above, but with reverse parameter set to True.

1

2

3

4

5

input_list = [4, 2, 5, 3, 1]

output_list = sorted(input_list, reverse=True)

print(input_list)  # [4, 2, 5, 3, 1]

print(output_list) # [5, 4, 3, 2, 1]



1

2

3

4

5

6

7

input_list = ["FOUR", "TWO", "FIVE", "THREE", "ONE"]

output_list = sorted(input_list, reverse=True)

print(input_list)  

# ['FOUR', 'TWO', 'FIVE', 'THREE', 'ONE']

print(output_list)
# ['TWO', 'THREE', 'ONE', 'FOUR', 'FIVE']


In both the cases, the list is sorted in a descending order. TypeError would still remain when data of different types is present in the list. 

Optional Parameter - key

Optional parameter 'key' accepts a function as a parameter and the default value is None. This parameter becomes extremely helpful where there is a nested lists (or tuples as elements). 

When a function is passed to the 'key' parameter, function is applied to each element and sorts the list based on the value returned. 

Let's get straight on to passing the lambda function for the key parameter.

By passing the function that returns the value of the element in the second element (i.e., index - 1), data would be sorted based the corresponding element. 

1

2

3

4

5

6

7

input_list = [(5, 5), (20, 2), (15, 3), (35, 1), (25, 4)]

output_list = sorted(input_list, key=lambda x:x[1])

print(input_list)

# [(5, 5), (20, 2), (15, 3), (35, 1), (25, 4)]

print(output_list)

# [(35, 1), (20, 2), (15, 3), (25, 4), (5, 5)]



In the above example, we are passing the lambda function that returns the element at the index - 1 for the list. This function is called for every element of the list and sorts the list in ascending order of the corresponding element. 

Functionality remains same as the sort() method (including any error scenarios  and not mentioning all of them here again. 

reverse() method

Using reverse parameter in sort() method or sorted() function helps in sorting the data in descending order. But, how do we just arrange the data in reverse order. 

I'm sure the first easiest thing that comes to the mind is that "slicing" way by passing '-1' as the step which returns the list in reverse order. 

1

2

3

4

input_list = [4, 2, 5, 3, 1]

output_list = input_list[::-1]

print(output_list) # [1, 3, 5, 2, 4]



There is a list method 'reverse()' which does this. This method modified the list in-place and return None. 

1

2

3

4

input_list = [4, 2, 5, 3, 1]

input_list.reverse()

print(input_list) # [1, 3, 5, 2, 4]



reverse() method does not have any parameters and modifies the list on which method is called. 

There is another function 'reversed()' which returns the reversed list instead of modifying the list in-place, it returns a 'reversed object' which can used as an iterator. 

reversed() function

reversed() function accepts any iterable (list, tuple or set) as a parameter and returns an iterable i.e., 'reversed object'. It does not modify the iterable passed.

1

2

3

4

5

input_tuple = (4, 2, 5, 3, 1)

output_list = reversed(input_tuple)

for element in output_list:

   print(element)



If the output needs to be a list instead of reversed object, this function can be called with in the list() function, which would convert the reversed object to a list. 

1

2

3

4

input_tuple = (4, 2, 5, 3, 1)

output_list = list(reversed(input_tuple))

print(output_list) # [1, 3, 5, 2, 4]




I hope this post has provided a good insight on different ways of sorting data in a List.

As my first attempt I have also created video with the same information on different ways of sorting data in Python. Feel free to have a look and your valuable feedback is highly appreciated.




If you have any Suggestions or Feedback, Please leave a comment below or use Contact Form.

Comments

Popular posts from this blog

All about READ in RPGLE & Why we use it with SETLL/SETGT?

READ READ is one of the most used Opcodes in RPGLE. As the name suggests main purpose of this Opcode is to read a record from Database file. What are the different READ Opcodes? To list, Below are the five Opcodes.  READ - Read a Record READC - Read Next Changed Record READE - Read Equal Key Record READP - Read Prior Record READPE - Read Prior Equal Record We will see more about each of these later in this article. Before that, We will see a bit about SETLL/SETGT .  SETLL (Set Lower Limit) SETLL accepts Key Fields or Relative Record Number (RRN) as Search Arguments and positions the file at the Corresponding Record (or Next Record if exact match isn't found).  SETGT (Set Greater Than) SETGT accepts Key Fields or Relative Record Number (RRN) as Search Arguments and positions the file at the Next Record (Greater Than the Key value). Syntax: SETLL SEARCH-ARGUMENTS/KEYFIELDS FILENAME SETGT  SEARCH-ARGUMENTS/KEYFIELDS FILENAME One of the below can be passed as Search Arguments. Key Fiel

What we need to know about CHAIN (RPGLE) & How is it different from READ?

CHAIN READ & CHAIN, These are one of the most used (& useful) Opcodes by any RPG developer. These Opcodes are used to read a record from file. So, What's the difference between CHAIN & READ?   CHAIN operation retrieves a record based on the Key specified. It's more like Retrieving Random record from a Database file based on the Key fields.  READ operation reads the record currently pointed to from a Database file. There are multiple Opcodes that start with READ and all are used to read a record but with slight difference. We will see more about different Opcodes and How they are different from each other (and CHAIN) in another article. Few differences to note.  CHAIN requires Key fields to read a record where as READ would read the record currently pointed to (SETLL or SETGT are used to point a Record).  If there are multiple records with the same Key data, CHAIN would return the same record every time. READE can be used to read all the records with the specified Ke

Extract a portion of a Date/Time/Timestamp in RPGLE - IBM i

%SUBDT Extracting Year, Month, Day, Hour, Minutes, Seconds or Milli seconds of a given Date/Time/Timestamp is required most of the times.  This can be extracted easily by using %SUBDT. BIF name looks more similar to %SUBST which is used to extract a portion of string by passing from and two positions of the original string. Instead, We would need to pass a value (i.e., Date, Time or Timestamp ) and Unit (i.e., *YEARS, *MONTHS, *DAYS, *HOURS, *MINUTES, *SECONDS or *MSECONDS) to %SUBDT.  Valid unit should be passed for the type of the value passed. Below are the valid values for each type. Date - *DAYS, *MONTHS, *YEARS Time - *HOURS, *MINUTES, *SECONDS Timestamp - *DAYS, *MONTHS, *YEARS, *HOURS, *MINUTES, *SECONDS, *MSECONDS Syntax: %SUBDT(value : unit { : digits { : decpos} }) Value and Unit are the mandatory arguments.  Digits and Decimal positions are optional and can only be used with *SECONDS for Timestamp. We can either pass the full form for the unit or use the short form. Below i