Given a pattern and a string str
, find if str
follows the same pattern.
Here follows means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str
.
Examples:
pattern = "abba"
, str = "dog cat cat dog"
should return true; dog
is a
, cat
is b
and the words form the abba
pattern.
pattern = "abba"
, str = "dog cat cat fish"
should return false; the string follows a abbc
pattern instead.
My solution works in Python 2:
def wordPattern(self, pattern, str):
s = pattern
t = str.split()
return map(s.find, s) == map(t.index, t)
But I am just wondering why this solution does not working in Python 3. There, the function will always return False
when trying to test the above examples. Could anyone please give some advice?
In Python 3, map()
returns an iterator object, not a list. Equality testing between these objects won't work (equality is testing for identity, the exact same object in memory, instead).
Convert to lists explicitly:
def wordPattern(self, pattern, str):
s = pattern
t = str.split()
return list(map(s.find, s)) == list(map(t.index, t))
or use list comprehensions:
def wordPattern(self, pattern, str):
s = pattern
t = str.split()
return [s.find(c) for c in s] == [t.index(w) for w in t]
or avoid creating lists altogether by comparing the zipped results with the all()
function:
from operator import eq
from itertools import starmap, zip_longest
def wordPattern(self, pattern, str):
s = pattern
t = str.split()
return all(starmap(eq, zip_longest(map(s.find, s), map(t.index, t))))
The latter short-circuits without having to make all comparisons if there is no match. In the spirit of keeping the functional style, I used itertools.starmap()
to test for equality with the operator.eq()
function. By using itertools.zip_longest()
we make sure that we can detect the case where the pattern length and word count don't match.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With