2015-10-26 7 views
6

私はキーが正規表現です辞書作成したい:正規表現を辞書のキーとして使用できますか?

d['apple'] 

私はリンゴ'apple'があるキーと照合することにしたい:私は辞書に見たときに、その後

d = {'a.*': some_value1, 'b.*': some_value2} 

を正規表現。 key/regular-expressionとの完全一致がある場合、対応する値が返されます。

たとえば、'apple'は、正規表現'a.*'と完全に一致します。したがって、some_value1が返されます。

もちろん、これはすべて正規表現キーが競合しないことを前提としています(つまり、2つのキーが同じ文字列と完全に一致してはならない)。キーを作成するときに、この要件を手動で処理できるとします。

これはPythonで可能ですか?もしそうなら、それは非常にエレガントで強力な構造物でしょう!

+2

「もしそうなら、それは非常にエレガントで強力な構造です!」 - 同じ文字列にマッチする正規表現を無制限に書くことができるので、そうではありません。あなたは正しい質問をしていません。あなたが解決しようとしている問題を説明してください。 – Tomalak

+2

互換性のないものが2つ必要です。プログラムは、正規表現と文字列の両方を少なくとも見ていなくても、正規表現が文字列にマッチするかどうかを判断することはできません。 _set_の正規表現(キー)と文字列を指定すると、どの正規表現がその文字列とマッチするかを知る唯一の方法は、すべての正規表現を試すことです。しかし、辞書のパフォーマンスは、すべてのキーを繰り返し処理する必要のない一致するキーを見つける能力に完全に基づいています。したがって、キーのあいまいさを避けることができたとしても、パフォーマンスはキーと値のペアのリストよりも優れていません。 –

答えて

1

ちょうどそれらを通常のように見て、マッチをチェックしてください。

import re 

def find_matches(d, item): 
    for k in d: 
     if re.match(k, item): 
      return d[k] 

d = {'a.*': 'a match', 'b.*': 'b match'} 
for item in ['apple', 'beer']: 
    print(find_matches(d, item)) 

結果:式が文字列のを開始で発見された場合にのみ、一致を生成

a match 
b match 

re.matchこと。式が文字列のどこにあってもよい場合は、re.searchを使用してください。

3

あなたは辞書のキーとしてre.compile Dパターンのオブジェクトを使用することができます。同じ正規表現を再コンパイルすることはあなたに(実際には同じオブジェクト、:re.compile('a.*') is d.keys()[0])同じキーを与えること

>>> import re 
>>> regex = re.compile('a.*') 
>>> d = {regex: 'foo'} 
>>> d[re.compile('a.*')] 
'foo' 

注ので、あなたが得ることができますあなたがそれに対抗して何を保存しても元に戻る。

しかし:

  • コメントで指摘したように、複数の正規表現は、同じ文字列を一致させることができます。
  • 辞書は順序付けられていないので、プログラムを実行するたびに異なる正規表現を最初に取得することがあります。
  • O(1)resultの値を{regex: result, ...}に入力する方法は、regexと一致する可能性のある文字列を指定してください。

このため、どのようなユーティリティが見つかるのは難しいです。


あなた何の2つのキーが同じ文字列に一致することはできません、あなたは新しいキーを追加する場合は、このチェックを適用してスキャンする__getitem__を実装MutableMappingサブクラスを作成することができることを確実にするための方法を考え出すことができる場合キーと値のペアを返し、最初の値を返します。引数がキー正規表現と一致する場合は、繰り返しますが、これはO(n)になります。

5

Python辞書はhash tablesとして実装されています。つまり、mydict[myvalue]の検索は、内部でハッシュしてmyvalueという非常に高速です。正規表現をキーとして使用すると、この機能がキャンセルされます。辞書を使用する代わりに、単純なリストまたはタプルを使用する必要があります。各項目は、(pattern/compiled regular expression, value)という形式のタプルで、正規表現が渡されるまでスキャンします。これはまた、あなた(たとえば、特定の一般的に)正規表現の順番で再生する機能を提供します:

import re 

LOOKUPS = [ 
    ('a.*', 'a'), 
    ('b.*', 'b'), 
] 

def lookup(s, lookups): 
    for pattern, value in lookups: 
     if re.search(pattern, s): 
      return value 
    return None 

print(lookup("apple", LOOKUPS)) 

は、あなたのアイデアの(非常に)高度な実装のためにも、Djangoのurl resolverを参照してください。

関連する問題