List Answers

List Exercises

Combined Lists

File: Edit the combine_lists function in the lists.py file that is in the exercises directory.

Test: Run python test.py combine_lists in your exercises directory.

Exercise: The function combine_lists should take two lists and return a new list containing all elements from both lists. To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from lists import combine_lists
>>> first = [1, 2, 3]
>>> second = [4, 5, 6]
>>> combine_lists(first, second)
[1, 2, 3, 4, 5, 6]

Note

Want to test this out manually (instead of using python test.py)?

You could could create a file called combine_lists_test.py with your own test code:

from lists import combine_lists

print("Calling combine_lists([1, 2, 3], [4, 5, 6])")
print("Expected: [1, 2, 3, 4, 5, 6]")
print("  Actual:", repr(combine_lists([1, 2, 3], [4, 5, 6])))

Then you can run that file to test your code:

$ python combine_lists_test.py

Answers

Idiomatic:

def combine_lists(one, two):
    """Return a new list that combines the two given lists."""
    return one + two

Longer:

def combine_lists(one, two):
    """Return a new list that combines the two given lists."""
    new_list = []
    new_list += one
    new_list += two
    return new_list

Using Methods:

def combine_lists(one, two):
    """Return a new list that combines the two given lists."""
    new_list = []
    new_list.extend(one)
    new_list.extend(two)
    return new_list

Rotate

File: Edit the rotate_list function in the lists.py file that is in the exercises directory.

Test: Run python test.py rotate_list in your exercises directory.

Exercise: The function rotate_list should remove the first item from a given list, add it to the end of the list, and return the item. To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from lists import rotate_list
>>> numbers = [1, 2, 3, 4]
>>> rotate_list(numbers)
1
>>> numbers
[2, 3, 4, 1]
>>> rotate_list(numbers)
2
>>> numbers
[3, 4, 1, 2]

Answers

def rotate_list(some_list):
    """Move first list item to end of list and return the item."""
    item = some_list.pop(0)
    some_list.append(item)
    return item

Reverse rotate

File: Edit the rotate_list function you just changed in the lists.py file that is in the exercises directory.

Test: Run python test.py rotate_list in your exercises directory.

Note

To run tests for this updated program, open lists_test.py, find the line that starts with class RotateListTests. Comment out the 2 lines with @unittest.skip to enable the tests for Reverse Rotate. These lines told the Test Framework to skip the tests because we didn’t expect the test to pass, but now we are changing the program so the test should pass, therefore we comment the line out.

Exercise: Modify rotate_list to accept a reverse argument which, if True, removes the last item (instead of the first) and adds the item to the beginning of the list (instead of the end). To test the function in the REPL, you can paste the function in from your text editor or import it as shown below.

>>> from lists import rotate_list
>>> numbers = [1, 2, 3, 4]
>>> rotate_list(numbers, reverse=True)
4
>>> numbers
[4, 1, 2, 3]
>>> rotate_list(numbers, reverse=False)
4
>>> numbers
[1, 2, 3, 4]

Answers

def rotate_list(some_list, reverse=False):
    """Move first list item to end of list and return the item.
       Or the reverse, based on reverse input value."""
    if reverse:
        item = some_list.pop()
        some_list.insert(0, item)
    else:
        item = some_list.pop(0)
        some_list.append(item)
    return item

Characters

File: Edit the characters function in the lists.py file that is in the exercises directory.

Test: Run python test.py characters in your exercises directory.

Exercise: The function characters takes a string and returns a list where each item is a single character from the string. All characters should be lowercased. Your function should accept an optional sort argument that, when True, will return the characters in ASCII-betical sorted order.

>>> from lists import characters
>>> characters("Trey Hunner")
['t', 'r', 'e', 'y', ' ', 'h', 'u', 'n', 'n', 'e', 'r']
>>> characters("Trey Hunner", sort=True)
[' ', 'e', 'e', 'h', 'n', 'n', 'r', 'r', 't', 'u', 'y']
>>> characters("hello", sort=False)
['h', 'e', 'l', 'l', 'o']
>>> characters("hello", sort=True)
['e', 'h', 'l', 'l', 'o']

Answers

def characters(string, sort=False):
    chars = []
    chars.extend(string.lower())
    if sort:
        chars.sort()
    return chars
def characters(string, sort=False):
    chars = list(string.lower())
    if sort:
        chars.sort()
    return chars
def characters(string, sort=False):
    if sort:
        return sorted(string.lower())
    else:
        return list(string.lower())

Reverse word order

File: Edit the reverse_words function in the lists.py file that is in the exercises directory.

Test: Run python test.py reverse_words in your exercises directory.

Exercise: The function reverse_words takes a string of words and returns a new sentence with the order of the words reversed. To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from lists import reverse_words
>>> reverse_words("words some are these")
'these are some words'
>>> reverse_words("who is this")
'this is who'

Answers

def reverse_words(sentence):
    """Return the given sentence with the words in reverse order."""
    return " ".join(reversed(sentence.split()))

Power By Index

File: Edit the ith_item_power function in the lists.py file that is in the exercises directory.

Test: Run python test.py ith_item_power in your exercises directory.

Exercise: The function ith_item_power accepts a list of numbers and an index number and returns the i-th element raised to the i-th power where i is the given index number. To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from lists import ith_item_power
>>> ith_item_power([3, 2, 5], 2)
25
>>> ith_item_power([5, 6, 2, 7, 3], 4)
81

Answers

def ith_item_power(nums, power):
    """Returns i-th element raised to the i-th power."""
    return nums[power] ** power

Natural Sort

Edit the natural_sort function in lists.py so that when given a list of words, it returns a new list with the words in “natural” sorted order. In other words, the new list will have the words sorted with the case of the words ignored.

Hint: Python has a built-in function sorted. However, when strings are sorted directly, all upper case letters come before lower case letters. You will need to create a key function to give to the sorted function as an argument. The key function for sorted accepts one item from the list, and returns the value that should be used for the sort.

To test with the automated tests, run python test.py natural_sort from the command line.

To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from lists import natural_sort
>>> fruits = ['Kiwi', 'orange', 'apple', 'Apricot', 'Grape', 'guava']
>>> sorted(fruits)
['Apricot', 'Grape', 'Kiwi', 'apple', 'guava', 'orange']
>>> natural_sort(fruits)
['apple', 'Apricot', 'Grape', 'guava', 'Kiwi', 'orange']

Answers

def natural_sort(words):
    """From list of words, return new list of words in natural sorted order."""
    def natural(word):
        return word.casefold()
    return sorted(words, key=natural)

Or directly using the casefold string method:

def natural_sort(words):
    """From list of words, return new list of words in natural sorted order."""
    return sorted(words, key=str.casefold)

Slice Exercises

Hint

If you get stuck for a minute or more, try searching Google or using help.

If you’re stuck for more than a couple minutes, some of these links might be helpful for some of the exercises below:

Last Words

File: Edit the last_words function in the slices.py file that is in the exercises directory.

Test: Run python test.py last_words in your exercises directory.

Exercise: Edit the function last_words that takes a string as an argument and will return a new string containing the last n words of the given string, separated by a space. To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from slices import last_words
>>> last_words("This is a sentence.", 2)
'a sentence.'
>>> last_words("Hello there", 1)
'there'
>>> last_words("hi", 2)
'hi'

Note

Want to test this out manually (instead of using python test.py)?

You could could create a file called last_words_test.py with your own test code:

from slices import last_words

print("Calling last_words('Many words in a sentence', 3)")
print("Expected: in a sentence")
print("  Actual:", last_words('Many words in a sentence', 3))

print()

print("Calling last_words('hello world', 2)")
print("Expected: hello world")
print("  Actual:", last_words('hello world', 2))

print()

print("Calling last_words('hi', 2)")
print("Expected: hi")
print("  Actual:", last_words('hi', 2))

Then you can run that file to test your code:

$ python last_words_test.py

Answers

def last_words(string, n):
    """Return the last words of the given string."""
    return " ".join(string.split()[-n:])

Note this does not work the way you might expect it to work if n is zero. You will get all the words joined together. You might argue that having n as zero is not valid input - after all, it doesn’t really make sense! If you want to handle this input condition, you can use:

def last_words(string, n):
    """Return the last words of the given string."""
    if n > 0:
        return " ".join(string.split()[-n:])
    return ""

Last N Elements

File: Edit the last_n_elements function in the slices.py file that is in the exercises directory.

Test: Run python test.py last_n_elements in your exercises directory.

Exercise: The function last_n_elements should use a slice to return the last n items of a list. This function should also accept an optional reverse argument, which when True, will reverse the order of the returned list. To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from slices import last_n_elements
>>> fruits = ['apples', 'grapes', 'peaches', 'apricots', 'bananas']
>>> last_n_elements(fruits, 3)
['peaches', 'apricots', 'bananas']
>>> last_n_elements(fruits, 1)
['bananas']
>>> last_n_elements(fruits, 3, reverse=False)
['peaches', 'apricots', 'bananas']
>>> last_n_elements(fruits, 3, reverse=True)
['bananas', 'apricots', 'peaches']
>>> numbers = [41, 25, 54, 15, 76, 68, 32, 38]
>>> last_n_elements(numbers, 4)
[76, 68, 32, 38]

Answers

def last_n_elements(sequence, n, reverse=False):
    """Return last 'n' items from given list.
       If argument 'reversed' is True, return in reversed order."""
    if n <= 0:
        return []
    if reverse:
        return sequence[:-n-1:-1]
    return sequence[-n:]
def last_n_elements(sequence, n, reverse=False):
    """Return last ``n`` items from given list."""
    if reverse:
        return sequence[-n:][::-1]
    else:
        return sequence[-n:]

Half

File: Edit the split_in_half function in the slices.py file that is in the exercises directory.

Test: Run python test.py split_in_half in your exercises directory.

Exercise: Make a function that splits a list in half and returns both halves. To test the function in the REPL, you can paste the function in from your text editor or import it as shown:

>>> from slices import split_in_half
>>> split_in_half([1, 2, 3, 4])
([1, 2], [3, 4])
>>> split_in_half([1, 2, 3, 4, 5])
([1, 2], [3, 4, 5])
>>> split_in_half([1, 2])
([1], [2])
>>> split_in_half([])
([], [])
>>> split_in_half([1])
([], [1])

Try your function on other iterables (strings or tuples). Does it still work?

>>> split_in_half("Hello world!")
('Hello ', 'world!')
>>> split_in_half((1, 2))
((1,), (2,))

Answers

One Line:

   def split_in_half(things):
       """Return two halves of the given iterable."""
       return (things[:len(things) // 2], things[len(things) // 2:])

With Variable:
def split_in_half(things):
    """Return two halves of the given iterable."""
    half_way = len(things) // 2
    return things[:half_way], things[half_way:]

Tags Equal

Edit the tags_equal function in slices.py to accept two strings containing opening HTML tags and return True if they have the same attributes with the same values.

Some examples:

>>> from slices import tags_equal
>>> tags_equal("<img src=cats.jpg width=200 height=400>", "<IMG SRC=Cats.JPG height=400 width=200>")
True
>>> tags_equal("<img src=dogs.jpg width=999 height=400>", "<img src=dogs.jpg width=200 height=400>")
False
>>> tags_equal("<p>", "<P>")
True
>>> tags_equal("<b>", "<p>")
False

You can assume:

  1. Attributes don’t have double/single quotes around them

  2. Attributes don’t contain spaces (until you get bonus 3)

  3. Attribute names will not be repeated

  4. All attributes will have values

  5. Attributes have no extra whitespace around them (key=value and never key = value)

Keep in mind that:

  1. Attribute names and values matter, but ordered must be ignored

  2. Attributes are case-insensitive (you’ll need to normalize the case)

Answers

def tags_equal(tag1, tag2):
    """Return True if the given HTML open tags represent the same thing."""
    items1 = tag1[1:-1].split()
    name1 = items1[0].lower()
    attrs1 = sorted(a.lower() for a in items1[1:])
    items2 = tag2[1:-1].split()
    name2 = items2[0].lower()
    attrs2 = sorted(a.lower() for a in items2[1:])
    return name1 == name2 and attrs1 == attrs2
def tags_equal(tag1, tag2):
    """Return True if the given HTML open tags represent the same thing."""
    attrs1 = tag1[1:-1].lower().split()
    attrs2 = tag2[1:-1].lower().split()
    return (attrs1[0], sorted(attrs1[1:])) == (attrs2[0], sorted(attrs2[1:]))
def parse_tag(html_tag):
    """Return tuple of tag name and sorted attributes."""
    attrs = html_tag[1:-1].lower().split()
    return attrs[0], sorted(attrs[1:])


def tags_equal(tag1, tag2):
    """Return True if the given HTML open tags represent the same thing."""
    return parse_tag(tag1) == parse_tag(tag2)