Slicing

Slicing

What if we want to get a consecutive number of elements from a list, but not the whole list?

We can use slices to get elements starting from one index, up to but not including another index.

>>> fruits = ["apples", "oranges", "bananas", "strawberries"]
>>> fruits[0:2]
['apples', 'oranges']
>>> fruits[1:3]
['oranges', 'bananas']

If we want to start our slice from the beginning of the list, we can leave out the first number:

>>> fruits[:2]
['apples', 'oranges']

Similarly if we want to end our slice at the end of the list, we can leave out the last number:

>>> fruits[2:]
['bananas', 'strawberries']
>>> fruits[2:len(fruits)]
['bananas', 'strawberries']

The “non-inclusive” aspects of slicing can be confusing at first, but it can be very useful as slicing from beginning to num and from num to end will give us non-overlapping lists:

>>> num = 3
>>> fruits[:num]
['apples', 'oranges', 'bananas']
>>> fruits[num:]
['strawberries']
>>> num = 1
>>> fruits[:num]
['apples']
>>> fruits[num:]
['oranges', 'bananas', 'strawberries']

One cool aspect of slicing is that we won’t get an error, even if we slice past the ends of our list. If we want the first 6 items of the list, we don’t have to worry about whether there are actually 6 items in the list, Python give us as many as it can:

>>> fruits[:6]
['apples', 'oranges', 'bananas', 'strawberries']
>>> fruits[-100:100]
['apples', 'oranges', 'bananas', 'strawberries']

If we give it numbers that don’t make sense, we just get an empty list back.

>>> fruits[6:2]
[]

Slices also allow for a third number that represents the step. The default step is 1. If we increase the step, the gap between our returned indices will increase:

>>> numbers = [2, 1, 3, 4, 7, 11, 18, 29]
>>> numbers[::1]
[2, 1, 3, 4, 7, 11, 18, 29]
>>> numbers[::2]
[2, 3, 7, 18]
>>> numbers[::3]
[2, 4, 18]

If we use a negative number our slice will start counting from the end of the list:

>>> numbers[::-1]
[29, 18, 11, 7, 4, 3, 1, 2]
>>> numbers[::-2]
[29, 11, 4, 1]

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

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]

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,))

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)