Learn Python Series (#6) - Handling Lists Part 2

in utopian-io •  7 years ago  (edited)

Learn Python Series (#6) - Handling Lists Part 2

python_logo.png

What Will I Learn?

  • You will learn about how to to remove list elements and entire lists themselves,
  • how to use lists as stacks,
  • how to reorder lists, either simple or by using a very powerful self-defined sorting criterium,
  • how to enumerate, zip / transpose and loop over lists.

Requirements

  • A working modern computer running macOS, Windows or Ubuntu
  • An installed Python 3(.6) distribution, such as (for example) the Anaconda Distribution
  • The ambition to learn Python programming

Difficulty

Intermediate

Curriculum (of the Learn Python Series):

Learn Python Series (#6) - Handling Lists Part 2

In the previous Handling Lists Part 1 episode, we covered creating, copying, accessing, updating lists, and about adding elements to them in various ways. In this episode - Handling Lists Part 2 - we will continue about lists, by explaining to remove list elements and entire lists themselves, how to use lists as stacks, how to reorder lists, either simple or by using a very powerful self-defined sorting criterium, how to enumerate, zip and transpose and loop over lists.

Removing elements from a list

list.pop([i])

The method pop() by default removes and returns the last element of a list. However, pop() also accepts an optional index argument i with which you can remove and return any element from the list. For example:

list4 = ['a', 'b', 'c', 'd', 'e']

# remove and return the last element 'e'
char = list4.pop()
print(char, list4)
# e ['a', 'b', 'c', 'd']

# remove and return the element at index 1 ('b')
char = list4.pop(1)
print(char, list4)
# b ['a', 'c', 'd']
e ['a', 'b', 'c', 'd']
b ['a', 'c', 'd']

PS: Trying to pop() from an empty list, will raise a IndexError.

list.remove(x)

Like pop, remove() (you probably guessed it already) removes elements from the list. But unlike pop(), the remove() method doesn't return elements, nor does it take an index but an element value as its argument. If it finds more than one element matching the argument, it removes the first one / the one with the lowest index. And in case the value wasn't found, remove() raises a ValueError. For example:

list5 = ['f', 'g', 'h', 'i', 'j', 'f']

# let's remove the 'f'
list5.remove('f')
print(list5)
# ['g', 'h', 'i', 'j', 'f']
# Please notice the last 'f' is still in the list

# let's remove the last 'f',
# by calling it again
list5.remove('f')
print(list5)
# ['g', 'h', 'i', 'j']
# Notice now the last 'f' is indeed removed

# if we try to remove an 'a',
# which isn't in the list,
# we get the error
list5.remove('a')
print(list5)
'''
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-28-52c373f4c8bb> in <module>()
     17 # which isn't in the list,
     18 # we get the error
---> 19 list5.remove('a')
     20 print(list5)

ValueError: list.remove(x): x not in list
'''
['g', 'h', 'i', 'j', 'f']
['g', 'h', 'i', 'j']

list.clear()

The clear() method removes all elements from a list, ergo, emoties the list. clear() doesn't take an argument or return a value. clear() also clears referenced ("copied") variable versions of the "original" list. Hopefully, the following examples make sense explaining this:

# In case we have two variables,
# both initially containing the same
# elements, and set one of them (`x`)
# to an empty list, the other one (`y`)
# still holds its elements.
x = y = [4,5,6]
x = []
print(x, y)
# [] [4, 5, 6]

# Using `clear()` on `x`, because `y` is set as
# a reference to `x`, indeed also clears `y`!
x = y = [4,5,6]
x.clear()
print(x, y)
# [] []

# You could also do this...
x = y = [4,5,6]
x[0:len(x)] = []
print(x, y)
# [] []

# ... which is equivalent to this
x = y = [4,5,6]
x[:] = []
print(x, y)
# [] []
[] [4, 5, 6]
[] []
[] []
[] []

The del statement

The del statement is yet another way to remove individual list elements, or a slice of list elements, remove all elements, and even remove an entire list (effectively deleting the variable previously assigned to the list). del just removes / deletes, and doesn't return a value. As a result, del can be used to replace all functionality the list methods remove() and clear() provide, plus delete the entire variable and list (as opposed to only emptying its elements).

Please regard the following examples on how to use del:

my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print(my_list)
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

# remove value at index 0
del my_list[0]
print(my_list)
# ['b', 'c', 'd', 'e', 'f', 'g', 'h']

# remove slice [0:3]
del my_list[0:3]
print(my_list)
# ['e', 'f', 'g', 'h']

# clear the entire list
del my_list[:]
print(my_list)
# []

# delete the list completely
del my_list
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
['b', 'c', 'd', 'e', 'f', 'g', 'h']
['e', 'f', 'g', 'h']
[]

LIFO Stacking with lists using append() and pop()

In case you want to use lists to function as a LIFO ("Last-In First-Out") Stack, you can very easily do so by using only the list methods list.append() and list.pop() (without passing in an index argument to pop()).

append() "puts" a new item "on top of the stack", and pop() "picks up" the last item "on top of the stack". For example:

my_stack = ['a', 'b', 'c']
new_order = 'd'
my_stack.append(new_order)
print(my_stack)
# ['a', 'b', 'c', 'd']
new_order = 'e'
my_stack.append(new_order)
print(my_stack)
['a', 'b', 'c', 'd', 'e']
my_stack.pop()
print(my_stack)
# ['a', 'b', 'c', 'd']
my_stack.pop()
print(my_stack)
# ['a', 'b', 'c']
my_stack.pop()
print(my_stack)
# ['a', 'b']
my_stack.pop()
print(my_stack)
# ['a']
my_stack.pop()
print(my_stack)
# []
['a', 'b', 'c', 'd']
['a', 'b', 'c', 'd', 'e']
['a', 'b', 'c', 'd']
['a', 'b', 'c']
['a', 'b']
['a']
[]

Reordering elements in a list

list.reverse()

The reverse() method doesn't take an argument, nor does it return a value. It simply reverses the order of all elements in the list. For example:

list8 = [5, 4, 3, 2, 1]
list8.reverse()
print(list8)
# [1, 2, 3, 4, 5]

list9 = ['a', 'c', 'e', 'b', 'd']
list9.reverse()
print(list9)
# ['d', 'b', 'e', 'c', 'a']
[1, 2, 3, 4, 5]
['d', 'b', 'e', 'c', 'a']

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

The sort() function orders / sorts the list elements to a given criteria. By default, the list elements are sorted in ascending order. If you want to sort in descending order, then pass in reverse=True as an agument.

In its simplest form, the sort() function is easy to use:

list6 = [7, 4, 6, 8, 3, 5, 1, 2, 9]

# Let's sort the list elements ascending
list6.sort()
print(list6)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Now let's sort the list elements descending
x = list6.sort(reverse=True)
print(x, list6)
# [9, 8, 7, 6, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
None [9, 8, 7, 6, 5, 4, 3, 2, 1]

The optional key parameter of sort() is a bit difficult to explain, but powerful and useful nonetheless, because it allows you to define your own sorting criterium, so not just ascending or descending. The value of key needs to be a function, either self-defined or built-in, that takes a single argument and returns a key. For example:

# Let's sort by string size, ascending,
# by passing in the `len()` function as the `key` argument
list7 = ['This', 'is', 'an', 'example', 'for', 'everybody']
list7.sort(key=len)
print(list7)
# ['is', 'an', 'for', 'This', 'example', 'everybody']

# Now let's define a self-built function,
# that takes a (word) string as argument
# and returns the last character in it

def last_char(word):
    return word[-1]

# If we now pass in the `last_char()` function
# as  the `key` argument, we're sorting
# the elements by their last character, ascending! ;-)
list7 = ['This', 'is', 'an', 'example', 'for', 'everybody']
list7.sort(key=last_char)
print(list7)
# ['example', 'an', 'for', 'is', 'This', 'everybody']
# last characters ascending: ['e', 'n', 'r', 's', 's', 'y']
['is', 'an', 'for', 'This', 'example', 'everybody']
['example', 'an', 'for', 'This', 'is', 'everybody']

Commonly-used List / List Looping Techniques

The enumerate() function

Usage: enumerate(iterable, start=0)

enumerate(), which by itself returns an enumerate object, adds a counter to a sequence, such as a list, or an iterable, so both the index positions and the element values can be retrieved all at once. Normally, when looping over a list, only the element values are returned, but not their index positions. Wrapping the list as an argument for enumerate() solves that problem.

By passing in an integer value for the optional keyword argument start as well, you can change the counter to start from that number.For example:

# Output tuples containing `(index, value)`
for item in enumerate(list('Hello!')):
    print(item)
# Output:
# -------
# (0, 'H')
# (1, 'e')
# (2, 'l')
# (3, 'l')
# (4, 'o')
# (5, '!')

# Output `index` and `value` individually
for index, value in enumerate(list('Hello!')):
    print(index, value)
# Output:
# -------
# 0 H
# 1 e
# 2 l
# 3 l
# 4 o
# 5 !

# Pass in an optional start value to change the indexes
for index, value in enumerate(list('Hello!'), 10):
    print(index, value)
# Output:
# -------   
# 10 H
# 11 e
# 12 l
# 13 l
# 14 o
# 15 !
(0, 'H')
(1, 'e')
(2, 'l')
(3, 'l')
(4, 'o')
(5, '!')
0 H
1 e
2 l
3 l
4 o
5 !
10 H
11 e
12 l
13 l
14 o
15 !

If you wrap the enumerate() function (that wraps a list itself) inside of another list, a list containing tuple elements, containing index, value pairs, is returned:

djs = list(enumerate(['Tiesto', 'Hardwell', 'Martin Garrix']))
print(djs)
# [(0, 'Tiesto'), (1, 'Hardwell'), (2, 'Martin Garrix')]
[(0, 'Tiesto'), (1, 'Hardwell'), (2, 'Martin Garrix')]

The zip() function

Using the zip() function it's possible to loop over 2 or more lists at the same time, like a "zipper", using the same index iterator for all zipped lists. This can be useful to transpose lists. For example:

a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]

# Transpose lists 
for item in zip(a, b, c):
    print(list(item))
# [1, 4, 7]
# [2, 5, 8]
# [3, 6, 9]
[1, 4, 7]
[2, 5, 8]
[3, 6, 9]

The reversed() function

The reversed() function allows you to reverse the element ordering of a list, so you can loop in reversed order, like so:

nums = [1, 2, 3]

for num in reversed(nums):
    print(num)
# 3
# 2
# 1
3
2
1

The sorted() function

Like the list.sort() method, by using the sorted() function you can loop in an ascending, descending, or self-defined order, like this:

accounts = ['@scipio', '@paulag', '@ghasemkiani', '@amosbastian', '@elear']

for acc in sorted(accounts):
    print(acc)
# @amosbastian
# @elear
# @ghasemkiani
# @paulag
# @scipio
@amosbastian
@elear
@ghasemkiani
@paulag
@scipio

What did we learn, hopefully?

Combined with Handling Lists Part 1, we now have plenty of tools on our toolbelt to use and completely control lists.

In the following episodes, we'll first expand on Handling Dictionaries, another important and very useful Python data type we haven't covered in-depth yet. Then we'll talk about importing packages, modules, classes either built-in your Python distribution, your self-written files, and/or external libraries. To those new to Python, you might not believe the enormous power and various tools you can use to code just about anything you want, with ease, using Python. See you there!

Thank you for your time!



Posted on Utopian.io - Rewarding Open Source Contributors

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

resteeming so I see the series first next time i come online. Thanks for doing this! (Going to follow on Raspberry Pi)

Thx! And enjoy the series!

Thank you for the contribution. It has been approved.

Great tutorial once again, but I was wondering what the difference between list.sort() and sorted() is (when would you use one over the other)?

You can contact us on Discord.
[utopian-moderator]

list.sort() modifies the existing list, while sorted() returns a new list without modifying the given list.

Hey @ scipio, great post! I enjoyed your content. Keep up the good work!
It's always nice to see good content here on Steemit! Cheers :)

@scipio, Contribution to open source project, I like you and upvote.

This is one of the best posts

Hey @scipio I am @utopian-io. I have just upvoted you!

Achievements

  • Seems like you contribute quite often. AMAZING!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x