6

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?

2
  • 2
    map returns a generator in python 3 Commented Feb 13, 2018 at 13:28
  • 1
    Use list(map(...)) Commented Feb 13, 2018 at 13:30

1 Answer 1

10

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.

Sign up to request clarification or add additional context in comments.

8 Comments

thanks for the corrections :) yours already tells the story to tell so mine is superflous.
I heard that list1 == list2 comparisons short circuit too, is that right? see comment here stackoverflow.com/a/18410924/6260170
@Chris_Rands: it does, but you first have to do two full iterations to create the lists.
@MartijnPieters I think that the last solution only works if s and t have the same number of elements. Did I miss something?
wordPattern(None, "abba", "dog cat cat dog dog") should return false and the last example returns true. You should check the number of elements first, i think
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.