Don't iterate over the indices of a list only to then access the element at that index. Instead iterate directly over the elements of the list! Have a look at Loop Like A Native by Ned Halder.
In the standard library module itertools
there is the groupby
function, which groups equal elements together. You can use this to make your code easier:
from itertools import groupby
def max_streaks(tosses):
longest_streaks = {"Heads": 0, "Tails": 0}
for toss, streak in groupby(tosses):
longest_streaks[toss] = max(longest_streaks[toss], len(list(streak)))
return longest_streaks["Heads"], longest_streaks["Tails"]
max_streaks("Heads, Tails, Tails, Tails, Heads, Heads, Tails".split(", "))
# 2, 3
Note that this does not assume anything about tosses
, unlike your code. It could be a list or a string, but also something like a generator, which has no len
.
You could generalize this function to being able to count the longest streak of any elements by using a collections.defaultdict
and returning it:
from collections import defaultdict
from itertools import groupby
from typing import Dict, Iterable, Hashable
def longest_streaks(elements: Iterable[Hashable]) -> Dict[Hashable, int]:
"""Count the length of the longest streak of each distinct element
present in `elements`.
All elements need to be hashable.
"""
longest_streak = defaultdict(int)
for element, streak in groupby(elements):
longest_streak[element] = max(longest_streak[element], len(list(streak)))
return dict(longest_streak)
if __name__ == "__main__":
longest_streaks([1, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 3])
# {1: 3, 2: 2, 3: 3}
Note that I followed Python's official style-guide, PEP8, by using lower_case
for variables and functions and wrapped the calling code in a if __name__ == "__main__":
guard to allow importing from this script without running the example. I also added some type hints and a docstring, which makes it easier to figure out what a function does, both for anybody else reading your code and for yourself in two months.