Lists, Tuples and Sets

Lists

A List in Python is the same an array in other programming languages (Java, C), its an ordered collection of objects. You don't have to worry about declaring the list or fixing its size ahead of time, the list itself will grow and shrink automatically as you add/remove elements. One big difference with Python Lists is that you can mixed data types, I will show you an example of this below. Like other programming languages the first index (element) starts at 0, but also have options to get the last element or second to last element using -1 or -2, etc, basically a negative number works it way from the back of the List.

Python can extract or assign to an entire sublist at once—an operation known as slicing. Instead of entering list[index] to extract the item just after index, enter list[index1:index2] to extract all items including index1 and up to (but not including) index2 into a new list

Lastly you can modify, sort (even custom sort), list membership, concatenate lists and do many other things with lists

Below is some example on using and displaying Lists

Creating
x = []             # creates an empty list
        x = [1, 2, 3, 4]
x = [2, "two", [1, 2, 3]]
Listing
x = ["first", "second", "third", "fourth"]
        
print(x[0])
print(x[2])
Length
x = ["first", "second", "third", "fourth"]
        
len(x)
Modifying
x = [1, 2, 3, 4]
x[len(x):] = [5, 6, 7]                  # results in [1, 2, 3, 4, 5, 6, 7] 

x = [1, 2, 3]
x.insert(2, "hello")                    # results in [1, 2, 'hello', 3]

x = [1, 2, 3]
x.insert(-1, "hello")                   # results in [1, 2, 'hello', 3], notice the negative index position

Note: you have other functions like append() or extend()
deleting
x = ['a', 2, 'c', 7, 9, 11]
del x[1]                         # results in ['a', 'c', 7, 9, 11], remember Lists start from 0

x = ['a', 'c', 7, 9, 11]
del x[:2]                        # results in [7, 9, 11]

x = [1, 2, 3, 4, 3, 5]
x.remove(3)                      # results in [1, 2, 4, 3, 5], it removes the first occurence
Reversing
x = ["first", "second", "third", "fourth"]
        
x.reverse()
print(x)
Sorting
x = [3, 8, 4, 0, 2, 1]
x.sort()                         # results in [0, 1, 2, 3, 4, 8]

x = ["Life", "Is", "Enchanting"]
x.sort()                         # results in ['Enchanting', 'Is', 'Life']

x = (4, 3, 1, 2)
y = sorted(x)                    # results in [1, 2, 3, 4]

z = sorted(x, reverse=True)      # results in [4, 3, 2, 1]

Note: sort() will change the original list, sorted() function returns a sorted list from any iterable
Membership
3 in [1, 3, 4, 5]                     # results in True
3 not in [1, 3, 4, 5]                 # results in False
3 in ["one", "two", "three"]          # results in False
3 not in ["one", "two", "three"]      # results in True
Concatenation
z = [1, 2, 3] + [4, 5]                # Results in [1, 2, 3, 4, 5]
Initialize
(pre-load)
z = [None] * 4                        # results in [None, None, None, None]
y = ['y'] * 4                        # results in ['y', 'y', 'y', 'y']
Minimum/
Maximum
min([3, 7, 0, -2, 11])                # results in -2
max([3, 7, 0, -2, 11])                # results in 11

Note: min/max are generally used with numbered Lists
Searching
x = [1, 3, "five", 7, -2]
x.index(7)                             # results in 3
Counting
x = [1, 2, 2, 3, 5, 2, 5]
x.count(2)                 # results in 3
x.count(5)                 # results in 2
x.count(4)                 # results in 0
Sums items
x = [1, 2, 2, 3, 5, 2, 5]
 y = sum(x)                     
 print(y)                  # results in 20
More List examples
parrot_list = ["not pinin", "no more", "a stiff", "bereft of life"]
parrot_list.append("Norwegian Blue")
for state in parrot_list:
    print("This parrot is " + state)

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

numbers = even + odd                    # you can also use extend() or append () method, see below 
numbers.sort()                          # sort and save to original object
numbers_in_order = sorted(numbers)      # create new sorted object
print(numbers)

numbers_reversed = numbers              # both objects point to same list, use list() to create new object
numbers_reversed.sort(reverse=True)     # can reverse order, there is also reverse() function

# could use numbers_reversed = sorted(numbers, reverse=True)
print(numbers_in_order)
print(numbers_reversed)

if numbers == numbers_in_order:          # checking contents, not if objects are same
    print("numbers equals numbers_in_order")
else:
    print("numbers DOES NOT equals numbers_in_order")

print("\n------------------------------------------------------------------")

# the below are the same, create an empty list
list_1 = []
list_2 = list()

# confirm its a List object
print(list_1.__class__)
print(list_2.__class__)

list_3 = list("This should be broken into separate elements")
print(list_3)

print("\n------------------------------------------------------------------")
even_1 = [0, 2, 4, 6, 8]
odd_1 = [1, 3, 5, 7, 9]

list_within_list = [even_1, odd_1]
print(list_within_list)

print("\n------------------------------------------------------------------")
menu = list()
menu.append(["egg", "spam", "bacon"])
menu.append(["egg", "sausage", "bacon"])
menu.append(["egg", "spam"])
menu.append(["egg", "bacon", "spam"])
menu.append(["egg", "bacon", "sausage", "spam"])
menu.append(["spam", "bacon", "sausage", "spam"])
menu.append(["spam", "egg", "spam", "spam", "bacon", "spam"])
menu.append(["spam", "egg", "sausage", "spam"])

print(menu)

for meal in menu:
    if not "spam" in meal:
        for item in meal:
          print(item, end=', ')

Nested lists and deep copies

Lists can be nested these are commonly called multi-dimensional arrays, you don't want to go to extremes level but two or three dimensional are usually ok, before they become too complex, with Lists you need to be aware of shallow and deep copies, which can be summarized below

Nested arrays
m = [[0, 1, 2], [10, 11, 12], [20, 21, 22]]

m[0]                 # results in [0, 1, 2]
m[0][1]              # results in 1
m[2]                 # results in [20, 21, 22]
m[2][2]              # results 22
Shallow and Deep Copies
original = [[0], 1]
shallow = original[:]

import copy
deep = copy.deepcopy(original)

Tuples

Tuples are data structures that are very similar to lists, but they can’t be modified (they are are immutable); they can only be created. Tuples are so much like lists that you may wonder why Python bothers to include them, the reason is that tuples have important roles that can’t be efficiently filled by lists, such as keys for dictionaries.

Tuple Basics
my_tuple = "a", "b", "c"    # you can surround with brackets
print(my_tuple)             # notice the printed brackets

x = ('a', 'b', 'c')         # the normal way to create tuple using brackets
        
x[2]                 # results in 'c'
x[1:]                # results in ('b', 'c')
len(x)               # results in 3 
max(x)               # results in 'c'
min(x)               # results in 'a'
5 in x               # results in False
5 not in x           # results in True

Note: as you can see functions used fir Luists can also be used for tuples.
Gotcha's with tuples
x = 3
y = 4
(x + y)              # This line adds x and y and results in 7
(x + y,)             # Including a comma indicates that the parentheses denote a tuple and results in (7,)
()                   # To create an empty tuple, use an empty pair of parentheses, results in ()

a, *b, c = x
a, b, c              # results in a tuple of (1, [2, 3], 4)
Packing and Unpacking
(one, two, three, four) = (1, 2, 3, 4)
        
one                  # results in 1
two                  # results in 2
Converting lists and tuples
list((1, 2, 3, 4))                 # coverts a tuple into a List of [1, 2, 3, 4]
tuple([1, 2, 3, 4])                # coverts a list into a tuple of (1, 2, 3, 4)
Advanced example of using tuples
welcome = "Welcome to my nightmare", "Alice Cooper", 1975
bad = "Ban Company", "Bad Company", 1974
budgie = "Nightflight", "Budgie", 1981
imelda = "More Mayhem", "Emilda May", 2011, ([(1, "Pulling the rug"),
                                             (2, "Psycho"),
                                             (3, "Mayhem"),
                                             (4, "Kentish Town Waltz")])

print(imelda)
title, artist, year, tracks = imelda

# because we have a list of tuples we can append
tracks.append((5, "All for You"))

print(title)
print(artist)
print(year)

for track in tracks:
    print("{}. {}".format(track[0], track[1]))

Sets

A set in Python is an unordered collection of objects used when membership and uniqueness in the set are main things you need to know about that object. Like dictionary keys, the items in a set must be immutable and hashable. The below details what can and cannot be used with sets:

Because sets aren’t immutable and hashable, they can’t belong to other sets, a frozenset which is just like a set but can’t be changed after creation and because frozensets are immutable and hashable, they can be members of other sets

Set Basics
x = set([1, 2, 3, 1, 3, 5])
        
x                     # results in {1, 2, 3, 5}
x.add(6)              # results in {1, 2, 3, 5, 6}
x.remove(5)           # results in {1, 2, 3, 6}
1 in x                # results in True
4 in x                # results in False

y = set([1, 7, 8, 9])
x | y                 # results in {1, 2, 3, 6, 7, 8, 9}
x & y                 # results in {1}
x ^ y                 # resylts in {2, 3, 6, 7, 8, 9}
>>>
Frozen sets
x = set([1, 2, 3, 1, 3, 5])
z = frozenset(x)
z                     # result in frozenset({1, 2, 3, 5})
Set Examples
# sets are mutable objects (unless you use a frozenset)
# there is no ordering

farm_animals = {"sheep", "cow", "hen"}
print(farm_animals)

wild_animals = set(["lion", "tiger", "panther", "elephant", "hare"])
print(wild_animals)

wild_animals.add("horse")
wild_animals.add("ant")
print(wild_animals)

# you can also use remove
wild_animals.remove("ant")
print(wild_animals)

# to create a empty set, dont use {} this is a dictionary
empty_set = set()
print(empty_set.__class__)

even = set(range(0, 40, 2))
print(even)
print(len(even))

square_tuple = (4, 6, 9, 16, 25)
squares = set(square_tuple)
print(squares)
print(len(square_tuple))

print("Union")
print(even.union(squares))
print(even | squares)                   # can also use this instead of above
print(len(even.union(squares)))

print("Intersection")
print(even.intersection(squares))
print(even & squares)                   # can also use this instead of above
print(len(even.intersection(squares)))

print("difference")
print(sorted(even.difference(squares)))
print(sorted(even - squares))           # can also use this instead of above
print(len(even - squares))

print("Symmetric Difference")
print(even.symmetric_difference(squares))
print(even ^ squares)                   # can also use this instead of above
print(len(even.symmetric_difference(squares)))

print("Subsets and supersets")
tuple1 = set([4, 6, 16])
print("tuple1 is a subset of squares {}".format(tuple1.issubset(squares)))          # can use <= as well
print("squares is a superset of tuple1 {}".format(squares.issuperset(tuple1)))      # can use >= as well

frozen_set = frozenset(range(0, 10, 2))
#frozen_set.add                             ## add/pop, etc does not exist as its an immutable object