0
import re
collections ={}
collections [re.compile ('n.*')]='word that starts with n'

I expect collections ['never'] to return 'word that starts with n' but the above is not happening.

What I am doing wrong?

MiniMe
  • 1,057
  • 4
  • 22
  • 47
  • 8
    Why would you expect this to work? – Daniel Roseman Mar 22 '17 at 15:27
  • 1
    Because I am learning python ? – MiniMe Mar 22 '17 at 15:27
  • 2
    Dictionaries are indexed by hashable keys. Your `re` instance is just hashed (probably by using its memory address / object id) and that's it. No magic is performed. The lookup will just look for a matching hash. – languitar Mar 22 '17 at 15:29
  • 2
    Dicts don't work like that. The string `'never'` is a different thing from the regular expression object that you put in the dict. You can't use one to look up the other. – khelwood Mar 22 '17 at 15:29
  • Why would expect a string that begins with a lower-case N to match a regular expression *explicitly* designed to match strings that begin with an upper-case N? – Scott Hunter Mar 22 '17 at 15:29
  • That was a dumb copy and paste. I changed the example to n.* – MiniMe Mar 22 '17 at 15:30
  • 3
    [The XY problem](https://meta.stackexchange.com/a/66378) – khelwood Mar 22 '17 at 15:31
  • 1
    How would you expect this to work if a string could matched with multiple regexes in the dict? – wim Mar 22 '17 at 15:33
  • 2
    Dictionaries _merely hold data_ and don't do any processing of it. You put in a value with some key and you extract the same value using the same key. Using anything other than this key will, obviously, fail. – ForceBru Mar 22 '17 at 15:34
  • You have to remember hash of your pattern. `h = hash(re.compile ('n.*')) collections[h] = ... ` – Patrik Polakovic Mar 22 '17 at 15:34
  • @PatrikPolakovic: Or just save the regex as a variable? `h = re.compile('n.*') collections[h] = ''` – gen_Eric Mar 22 '17 at 15:41
  • @RocketHazmat, of course :) I am overextended today... – Patrik Polakovic Mar 22 '17 at 15:55
  • Hi, I've no idea why my answer get down (may not be caused by you). But acturally I think a custom function is what you need(even more than one regular expressions). @Eric Duminil did teach you a lot and also the other commenter, but I have to argue that he might complicate the problem and I think my answer is the simplest way that meet your requirement. If I did nothing to your question, I suggest you correct your question and make it more clear, sincerely. – Zealseeker Mar 22 '17 at 17:33
  • I did not down any reply in this thread – MiniMe Mar 22 '17 at 18:33

2 Answers2

5

Solution

No magic is happening here, so you'll have to iterate on every pair :

import re
collections = {}
collections[re.compile('n.*')] = 'word that starts with n'
collections[re.compile(r'\b....\b')] = '4 letter word'


def find_matching_regexen(word, dicts=collections):
    return [description for regex, description in dicts.items() if regex.match(word)]

print(find_matching_regexen('never'))
# ['word that starts with n']
print(find_matching_regexen('boat'))
# ['4 letter word']
print(find_matching_regexen('nice'))
# ['word that starts with n', '4 letter word']
print(find_matching_regexen('dog'))
# []

If the output order is important, you would have to use an OrderedDict

Note

From the zen of python :

Explicit is better than implicit.

If you want to achieve something in Python, you usually have to write it. The syntax might be short and clear, but it still needs to be written explicitely.

So no, a string will not be considered as having the same hash as a matching regex in a dict.

If you're looking for some more magic, you might take a look at Ruby. It has a broader definition of patterns, which can be classes, regexen or strings :

[1, "abc", 2, "def"].grep(/a/)
# => ["abc"]
[1, "abc", 2, "def"].grep(Integer)
# => [1, 2]

Patterns are also used in case statements. As an example, you can match a string with a regex without conversion or explicit method call:

def find_matching_regexen(word)
  case word
  when /^n.*/
    "Word that starts with n"
  when /\b....\b/
    "4 letter word"
  end
end

puts find_matching_regexen("boat")
# "4 letter word"
puts find_matching_regexen("nice")
# "Word that starts with n"
puts find_matching_regexen("dog")
# nil
Community
  • 1
  • 1
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
  • You should use an `OrderedDict` so the result is predictable – wim Mar 22 '17 at 15:38
  • 2
    @wim: It depends on what OP wants. I could use an `OrderedDict`. Since the above returns a list, the order might matter less than the content. – Eric Duminil Mar 22 '17 at 15:40
  • 2
    Thanks a lot guys, I am digesting the above. Seems that the first 5-6 responders were kind of young and rather inclined to make fun of you than to help you – MiniMe Mar 22 '17 at 15:42
  • @MiniMe: Or the opposite, they might have spent too much time on SO. Anyway, languitar's comment was actually decent and could be considered as being a valid answer. – Eric Duminil Mar 22 '17 at 16:00
-1
def collections(text):
  if re.compile('n.*').findall(text):
    return 'word that starts with n'
print collections('never')
>>> word that starts with n
Zealseeker
  • 823
  • 1
  • 7
  • 23