I have a tuple [but it can be any collection] that contains elements:
tple = (1.02, 'a', 'b', 1.02, 'a', 'b')
I’m trying to find a way to count the number of times the pattern (1.02, 'a', 'b') occurs within the tple. The pattern may not exist at all, in which case I would want to return 0.
Is there such a way?
>Solution :
One approach using itertools:
from itertools import tee
def wise(iterable):
"""Iterate over contiguous overlapping chunks"""
a, b, c = tee(iterable, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)
tple = (1.02, 'a', 'b', 1.02, 'a', 'b')
pattern = (1.02, 'a', 'b')
res = sum(i == pattern for i in wise(tple))
print(res)
Output
2
The function wise, is a generalization of itertools.pairwise. For the above example it returns something similar to:
[(1.02, 'a', 'b'), ('a', 'b', 1.02), ('b', 1.02, 'a'), (1.02, 'a', 'b')]
Note that by using itertools tple can be any collection. The expression:
res = sum(i == pattern for i in wise(tple))
is equivalent to the following for-loop:
res = 0
for i in wise(tple):
if pattern == i:
res += 1
print(res)
If you want to iterate in chunks of different lengths, use the following general wise function:
def wise(iterable, n=3):
"""Iterate over contiguous overlapping chunks"""
its = tee(iterable, n)
for i, it in zip(range(n), its):
for _ in range(i):
next(it)
return zip(*its)