Reputation: 443
I have a sequence of patterns and want to match strings against those patterns and return the first group. I am coming from a scala background but I found myself needing to do the same thing in Python. Is there anyway to map and match a collection of patterns?
The following is how it would look in scala
private val patterns = Stream(
Pattern.compile("([a-zA-Z\\d]{9}-[a-zA-Z\\d]{3})"),
Pattern.compile("([a-zA-Z\\d]{3}-[a-zA-Z\\d]{3}-\\d{4}-\\d{2})"),
Pattern.compile("([a-zA-Z\\d]{5}-[a-zA-Z\\d]{3}-\\d{4})"),
Pattern.compile("([a-zA-Z\\d]{5}-[a-zA-Z\\d]{3}-\\d{4})"),
Pattern.compile("([a-zA-Z\\d]{3}-[a-zA-Z\\d]{3}-\\d{4}-\\d{2})"),
Pattern.compile("([a-zA-Z\\d]{5}-[a-zA-Z\\d]{3}-\\d{4})"),
Pattern.compile("([a-zA-Z\\d!]{2,3}-[a-zA-Z\\d]{2,4}-[a-zA-Z\\d]{3,5}-[\\d]{1,2})"),
Pattern.compile("([a-zA-Z\\d]{3,6}-[a-zA-Z\\d]{3}-[\\d]{1,6})"),
Pattern.compile("([a-zA-Z\\d]{3,6}-[a-zA-Z\\d]{4}-[\\d]{1,6})")
)
patterns.map(_.matcher(sku)).find(_.matches()).map(_.group(1)
Upvotes: 0
Views: 159
Reputation: 3925
This relatively faithful transliteration works for me:
import re
patterns = [
re.compile("([a-zA-Z\\d]{9}-[a-zA-Z\\d]{3})"),
re.compile("([a-zA-Z\\d]{3}-[a-zA-Z\\d]{3}-\\d{4}-\\d{2})"),
re.compile("([a-zA-Z\\d]{5}-[a-zA-Z\\d]{3}-\\d{4})"),
re.compile("([a-zA-Z\\d]{5}-[a-zA-Z\\d]{3}-\\d{4})"),
re.compile("([a-zA-Z\\d]{3}-[a-zA-Z\\d]{3}-\\d{4}-\\d{2})"),
re.compile("([a-zA-Z\\d]{5}-[a-zA-Z\\d]{3}-\\d{4})"),
re.compile("([a-zA-Z\\d!]{2,3}-[a-zA-Z\\d]{2,4}-[a-zA-Z\\d]{3,5}-[\\d]{1,2})"),
re.compile("([a-zA-Z\\d]{3,6}-[a-zA-Z\\d]{3}-[\\d]{1,6})"),
re.compile("([a-zA-Z\\d]{3,6}-[a-zA-Z\\d]{4}-[\\d]{1,6})")
]
sku = "123456789-AAA"
res = filter(lambda x: x is not None, map(lambda x: x.match(sku), patterns))
print res[0].group(1)
Most likely, you could use a more Pythonic list comprehension, but the above approach mirrors your code very much.
It has one drawback - it doesn't stop at the first match but will evaluate all matches before returning the first.
Upvotes: 1