2. Lists, Sorting, and Tuples and Dictionaries

Basic Data Types

List

  • A data-structure that can store any type of data (objects).

  • Ordered collection and start with 0

  • List has mutable nature i.e., list can be changed or modified after its creation according to needs whereas tuple has immutable nature i.e., tuple can’t be changed or modified after its creation.

  • my_list = []

>>> my_list = ['hello', 1, 2, 3, [1, 2, 3]]
>>> def hello(greeting):
print(greeting)
>>> my_list.append(hello) # Appending the function to the list
>>> my_list
['hello', 1, 2, 3, [1, 2, 3], <function hello at 0x02F36D18>]
>>> my_list[0]
'hello'
>>> my_list[5]
<function hello at 0x02F36D18>
>>> my_list[5]('namaste') # Running the function - 'hello()'
namaste

Indexing

>>> orgs = [['AWS', 'Azure', 'GCP'], ['PayTM', 'PhonePay', 'Google Pay'], ['Amazon', 'Flipkart', 'Snapdeal', 'Myntra']]
>>> orgs[0][0]
'AWS'
>>> orgs[1][0]
'PayTM'
>>> orgs[2][0]
'Amazon'
>>> orgs[1][2]
'Google Pay'
>>> orgs[3][0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range

Accessing Index of a list using enumerate():

>>> friends = ["Sarthak", "Monica", "Himanshi"]
>>> for index, element in enumerate(friends):
print(f"Index: {index} | Friend Name: {element}")
Index: 0 | Friend Name: Sarthak
Index: 1 | Friend Name: Monica
Index: 2 | Friend Name: Himanshi

Find an index:

>>> orgs
[['AWS', 'Azure', 'GCP'], ['Amazon', 'Flipkart', 'Snapdeal', 'Myntra']]
>>> orgs[1].index('Myntra')
3

Append vs Extend

list.append() => appends an object to the end of the list.

>>> orgs = [['AWS', 'Azure', 'GCP']]
>>> orgs[2].index('Myntra')
3
>>> orgs.append('Grey Head Media')
>>> orgs
[['AWS', 'Azure', 'GCP'], 'Grey Head Media']
>>> orgs = [['AWS', 'Azure', 'GCP']]
>>> orgs.append(['DynamicCIO', 'ETCIO', 'EliteCIO'])
>>> orgs
[['AWS', 'Azure', 'GCP'], ['DynamicCIO', 'ETCIO', 'EliteCIO']]

list.extend() => appends a list to the list

>>> orgs = [['AWS', 'Azure', 'GCP']]
>>> orgs.extend(['DynamicCIO', 'ETCIO', 'EliteCIO'])
>>> orgs
[['AWS', 'Azure', 'GCP'], 'DynamicCIO', 'ETCIO', 'EliteCIO']

You can also use + but they are not the same. + creates a new list in the memory without modifying the original. Read more

>>> orgs = [['AWS', 'Azure', 'GCP']]
>>> orgs + ['DynamicCIO', 'ETCIO', 'EliteCIO'] # Creates a new list
[['AWS', 'Azure', 'GCP'], 'DynamicCIO', 'ETCIO', 'EliteCIO']
>>> orgs # The original stays the same
[['AWS', 'Azure', 'GCP']]

list.insert(index, "item") Insert the item at a specific position.

>>> orgs = ['AWS', 'Azure', 'GCP']
>>> orgs.insert(1, 'Digital Ocean')
>>> orgs
['AWS', 'Digital Ocean', 'Azure', 'GCP']

List Comprehension

This technique lets us create new lists based on sequences or ranges. So we can use this technique whenever we want to create a list based on a range like in this example. Or based on the contents of a list a tuple a string or any other Python sequence.

>>> multiple = []
>>> for i in range(1, 11):
multiple.append(i*7)
>>> multiple
[7, 14, 21, 28, 35, 42, 49, 56, 63, 70]
### List Comprehension: Example 1
>>> multiples = [ i*7 for i in range(1, 11)]
>>> multiples
[7, 14, 21, 28, 35, 42, 49, 56, 63, 70]
### Example 2: Generating length of each language
>>> languages = ["Python", "Java", "Perl", "Ruby", "C", "Go"]
>>> lang_lengths = [len(i) for i in languages]
>>> lang_lengths
[6, 4, 4, 4, 1, 2]
### Example 3: Generating a list that are divisible by 3
>>> z = [x for x in range(0,101) if x % 3 == 0]
>>> z
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]

Sorting

Basic sorting:

>>> a = [2,4,5,2,5,6]
>>> sorted(a)
[2, 2, 4, 5, 5, 6]
>>> a = ['aaaa', 'd', 'bb', 'ccc']
>>> sorted(a)
['aaaa', 'bb', 'ccc', 'd']

Advanced sorting:

Imagine you want to sort numbers based on the length of the items.

>>> a = ['aaaa', 'bb', 'ccc', 'd']
>>> sorted(a, key=len)
['d', 'bb', 'ccc', 'aaaa']

Imagine you want to sort it by the last character of the string.

>>> a = ['aaaa', 'd', 'bb', 'ccc']
>>> a[0] = 'aaaaz'
>>> a
['aaaaz', 'd', 'bb', 'ccc']
>>> def last(s):
... return s[-1]
...
>>> last('aaaaz')
'z'
>>> sorted(a, key=last)
['bb', 'ccc', 'd', 'aaaaz']

Tuples

  • Tuples are immutable i.e. once defined, can't be modified later. Notice the error message below.

  • my_tuple = ()

>>> my_tuple = ("BK", "AK", "SK", "MK")
>>> my_tuple[0]
'BK'
>>> for i in my_tuple:
print(i)
BK
AK
SK
MK
>>> my_tuple[0] = "PK"
Traceback (most recent call last):
File "<pyshell#86>", line 1, in <module>
my_tuple[0] = "PK"
TypeError: 'tuple' object does not support item assignment
>>> list_of_tuple = [("BK", 24), ("AK", 25), ("PK", 34)]
>>> type(list_of_tuple)
<class 'list'>
>>> list_of_tuple
[('BK', 24), ('AK', 25), ('PK', 34)]
>>> list_of_tuple[0]
('BK', 24)
>>> list_of_tuple[0][0]
'BK'
>>> for i in list_of_tuple:
print(f"Name: {i[0]}, Age: {i[1]}")
Name: BK, Age: 24
Name: AK, Age: 25
Name: PK, Age: 34

Dictionary

The data inside dictionaries take the form of pairs of keys and values.

  • Dictionaries are mutable i.e. you can change things inside.

  • my_dict = {}

>>> my_dict = {}
>>> type(my_dict)
<class 'dict'>
>>> file_counts = {"jpg": 20, "txt": 16, "png": 53, "py":29}
>>> file_counts
{'jpg': 20, 'txt': 16, 'png': 53, 'py': 29}
>>> "jpg" in file_counts
True
>>> "html" in file_counts
False
>>> file_counts = {"jpg": 20, "txt": 16, "png": 53, "py":29}
>>> file_counts["jpg"]
20
>>> file_counts["jpg"] = 25
>>> file_counts["jpg"]
25
>>> file_counts["cfg"] = 10
>>> file_counts
{'jpg': 25, 'txt': 16, 'png': 53, 'py': 29, 'cfg': 10}

Dictionary Operations:

Iterating over dictionary using different methods:

>>> file_counts = {"jpg": 20, "txt": 16, "png": 53, "py":29}
>>> for extension in file_counts:
print(extension)
jpg
txt
png
py
>>> for extension in file_counts:
print(file_counts[extension])
20
16
53
29
>>> for ext, num in file_counts.items():
print(f"There are {num} files with .{ext} extension")
There are 20 files with .jpg extension
There are 16 files with .txt extension
There are 53 files with .png extension
There are 29 files with .py extension
>>> for ext in file_counts.keys():
print(f".{ext} extension")
.jpg extension
.txt extension
.png extension
.py extension
>>> for num in file_counts.values():
print(f"{num} files")
20 files
16 files
53 files
29 files
>>> print(file_counts.values())
dict_values([20, 16, 53, 29])
>>> print(file_counts.keys())
dict_keys(['jpg', 'txt', 'png', 'py'])
>>> print(file_counts.items())
dict_items([('jpg', 20), ('txt', 16), ('png', 53), ('py', 29)])
>>> file_counts.get("png")
53
### Code for counting each letter in a text
>>> def count_letters(text):
result = {}
for letter in text:
if letter not in result:
result[letter] = 0
result[letter] += 1
return result
>>> count_letters("bablu")
{'b': 2, 'a': 1, 'l': 1, 'u': 1}
>>> count_letters("banana")
{'b': 1, 'a': 3, 'n': 2}

In Python, a dictionary can only hold a single value for a given key. To workaround this, our single value can be a list containing multiple values. Here we have a dictionary called "wardrobe" with items of clothing and their colors. Fill in the blanks to print a line for each item of clothing with each color, for example: "red shirt", "blue shirt", and so on:

>>> wardrobe = {"shirt":["red","blue","white"], "jeans":["blue","black"]}
>>> for key, elements in wardrobe.items():
for element in elements:
print ("{} {}".format (element, key))
red shirt
blue shirt
white shirt
blue jeans
black jeans

Dictionary Methods Cheat Sheet

Definition

x = {key1:value1, key2:value2}

Operations

  • len(dictionary) - Returns the number of items in the dictionary

  • for key in dictionary - Iterates over each key in the dictionary

  • for key, value in dictionary.items() - Iterates over each key,value pair in the dictionary

  • if key in dictionary - Checks whether the key is in the dictionary

  • dictionary[key] - Accesses the item with key key of the dictionary

  • dictionary[key] = value - Sets the value associated with key

  • del dictionary[key] - Removes the item with key key from the dictionary

Methods

  • dict.get(key, default) - Returns the element corresponding to key, or default if it's not present

  • dict.keys() - Returns a sequence containing the keys in the dictionary

  • dict.values() - Returns a sequence containing the values in the dictionary

  • dict.update(other_dictionary) - Updates the dictionary with the items coming from the other dictionary. Existing entries will be replaced; new entries will be added.

  • dict.clear() - Removes all the items of the dictionary

Set

Used when you want to store a bunch of elements and be certain that they are only present once.

Lab

The format_address function separates out parts of the address string into new strings: house_number and street_name, and returns: "house number X on street named Y". The format of the input string is: numeric house number, followed by the street name which may contain numbers, but never by themselves, and could be several words long. For example, "123 Main Street", "1001 1st Ave", or "55 North Center Drive". Fill in the gaps to complete this function.

def format_address(address_string):
add_list = address_string.split(" ", 1)
return f"house number {add_list[0]} on street named {add_list[1]}"
print(format_address("123 Main Street"))
# Should print: "house number 123 on street named Main Street"
print(format_address("1001 1st Ave"))
# Should print: "house number 1001 on street named 1st Ave"
print(format_address("55 North Center Drive"))
# Should print "house number 55 on street named North Center Drive"
Output:
house number 123 on street named Main Street
house number 1001 on street named 1st Ave
house number 55 on street named North Center Drive

The highlight_word function changes the given word in a sentence to its upper-case version. For example, highlight_word("Have a nice day", "nice") returns "Have a NICE day". Can you write this function in just one line?

def highlight_word(sentence, word):
return (sentence.replace(word,word.upper()))
print(highlight_word("Have a nice day", "nice"))
print(highlight_word("Shhh, don't be so loud!", "loud"))
print(highlight_word("Automating with Python is fun", "fun"))
Output:
Have a NICE day
Shhh, don't be so LOUD!
Automating with Python is FUN

A professor with two assistants, Jamie and Drew, wants an attendance list of the students, in the order that they arrived in the classroom. Drew was the first one to note which students arrived, and then Jamie took over. After the class, they each entered their lists into the computer and emailed them to the professor, who needs to combine them into one, in the order of each student's arrival. Jamie emailed a follow-up, saying that her list is in reverse order. Complete the steps to combine them into one list as follows: the contents of Drew's list, followed by Jamie's list in reverse order, to get an accurate list of the students as they arrived.

def combine_lists(list1, list2):
# Generate a new list containing the elements of list2
# Followed by the elements of list1 in reverse order
list1.reverse()
return list2 + list1
Jamies_list = ["Alice", "Cindy", "Bobby", "Jan", "Peter"]
Drews_list = ["Mike", "Carol", "Greg", "Marcia"]
print(combine_lists(Jamies_list, Drews_list))
Output:
['Mike', 'Carol', 'Greg', 'Marcia', 'Peter', 'Jan', 'Bobby', 'Cindy', 'Alice']

Use a list comprehension to create a list of squared numbers (n*n). The function receives the variables start and end, and returns a list of squares of consecutive numbers between start and end inclusively. For example, squares(2, 3) should return [4, 9].

def squares(start, end):
return [ x*x for x in range(start, end+1) ]
print(squares(2, 3)) # Should be [4, 9]
print(squares(1, 5)) # Should be [1, 4, 9, 16, 25]
print(squares(0, 10)) # Should be [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Complete the code to iterate through the keys and values of the car_prices dictionary, printing out some information about each one.

def car_listing(car_prices):
result = ""
for key, value in car_prices.items():
result += "{} costs {} dollars".format(key, value) + "\n"
return result
print(car_listing({"Kia Soul":19000, "Lamborghini Diablo":55000, "Ford Fiesta":13000, "Toyota Prius":24000}))
Output:
Kia Soul costs 19000 dollars
Lamborghini Diablo costs 55000 dollars
Ford Fiesta costs 13000 dollars
Toyota Prius costs 24000 dollars

Use a dictionary to count the frequency of letters in the input string. Only letters should be counted, not blank spaces, numbers, or punctuation. Upper case should be considered the same as lower case. For example, count_letters("This is a sentence.") should return {'t': 2, 'h': 1, 'i': 2, 's': 3, 'a': 1, 'e': 3, 'n': 2, 'c': 1}.

def count_letters(text):
result = {}
# Go through each letter in the text
for letter in text.lower():
# Check if the letter needs to be counted or not
if letter.isalpha():
if letter not in result:
result[letter] = 0
# Add or increment the value in the dictionary
result[letter] += 1
return result
print(count_letters("AaBbCc"))
# Should be {'a': 2, 'b': 2, 'c': 2}
print(count_letters("Math is fun! 2+2=4"))
# Should be {'m': 1, 'a': 1, 't': 1, 'h': 1, 'i': 1, 's': 1, 'f': 1, 'u': 1, 'n': 1}
print(count_letters("This is a sentence."))
# Should be {'t': 2, 'h': 1, 'i': 2, 's': 3, 'a': 1, 'e': 3, 'n': 2, 'c': 1}

Taylor and Rory are hosting a party. They sent out invitations, and each one collected responses into dictionaries, with names of their friends and how many guests each friend is bringing. Each dictionary is a partial list, but Rory's list has more current information about the number of guests. Fill in the blanks to combine both dictionaries into one, with each friend listed only once, and the number of guests from Rory's dictionary taking precedence, if a name is included in both dictionaries. Then print the resulting dictionary.

def combine_guests(guests1, guests2):
# Combine both dictionaries into one, with each key listed
# only once, and the value from guests1 taking precedence
Rorys_guests = { "Adam":2, "Brenda":3, "David":1, "Jose":3, "Charlotte":2, "Terry":1, "Robert":4}
Taylors_guests = { "David":4, "Nancy":1, "Robert":2, "Adam":1, "Samantha":3, "Chris":5}
print(combine_guests(Rorys_guests, Taylors_guests))