2016-04-14 6 views
2

は、だから私は、値のリストを持っている:INをオーバーロードせずに辞書メンバーシップ比較を定義しますか?

alist = list() 

をそして私は、リストのメンバーが辞書にあるかどうかを確認したい:

ahash = dict() #imagine I have filled a dictionary with data. 

for member in alist: 
    if member in hash: 
     #DO STUFF 

これは非常に簡単です。

私がしたいのは、ファジー比較を実装するためにINを再定義することです。だから、私がしたいのは、FOOBARBAZZとFOO *がFOOBARBAZZにマッチする*とマッチすることです。

私がこれを行うと考えることができる最も簡単な方法は、この全体的な状況をオブジェクトのメソッドとして実装し、次にIN演算子をオーバーロードします。しかし私自身の理由(完全にペタニック)のために、私はOOPのアプローチを避けたいと思います。

辞書を比較するたびに辞書全体をループせずに(これは間違っていると思いますが)、どのように辞書のカスタム比較を実装できますか?

追加番号: IN演算子にはIN以外に異なる名前がありますか?名前を付けることにより、検索エンジンでの検索が困難な情報がオペレータに表示されます。私はそれが__contains__と同じかもしれないと思いますが、私はまだ__contains__が辞書のためにどのように働いているのか見当たりません。

+0

'ahash = hash()'は誤った構文です! 'hash()'関数は辞書を作成せず、入力引数のハッシュ値を返します(ハッシュ可能な場合)。 – Kasramvd

+0

私はあなたが私の意味を理解したと思います。 – baordog

+0

O(n)の検索ソリューション(ハッシュテーブルから離れている)に戻ってくるので、この方法ではdictの効率が大幅に低下しています。何かが複数のキーに一致するとどうなりますか?リストを返しますか?最初の1つ? –

答えて

1

これに答える最善の方法は、alistの中で正規表現に「あいまい一致」させたいものを翻訳することです。次に、あなたが)(dict.keysに正規表現を適用することができ、例はここにあるかもしれない:

How to use re match objects in a list comprehension

はすでにあなたのファジーマッチのために定義された正式な言語があり、またはあなたが1を作っていますか?あなたがしたい場合

for member in alist: 
    regex = re.sub("\*", ".*", member) + "$" 
    if any([re.match(regex, x) for x in hash.keys()]): 
    # do stuff 

:末尾が「*」あなたは、あなたのソリューションは以下のようになり試合のために使用されている唯一のシンボルである場合は再へ「のfoo *」を回すには、

regex = re.sub("\*", ".*", list_element) + "$" 

によって行うことができますマッチングする言語をより強力にするためには、正規表現への翻訳をもっと複雑にするだけです。これは、ほとんどの点でdictのような役割を果たし

In [9]: class FuzzyDict(dict): 
    ...:  def __contains__(self, needle): 
    ...:   if '*' not in needle: 
    ...:    return super(FuzzyDict, self).__contains__(needle) 
    ...:   else: 
    ...:    for key in self.keys(): 
    ...:     if str(key).startswith(needle[:-1]): 
    ...:      return True 
    ...:    return False 
    ...: 

:あなたはdictタイプを内蔵しており、新しい__contains__方法(どのような舞台裏in呼び出しである)を定義をサブクラス化することができますinを上書きする

3

In [12]: my_dict = FuzzyDict(zip('abcde', range(1, 6))) 

In [13]: my_dict 
Out[13]: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5} 

In [14]: my_dict['apple'] = 6 

あなたはinテスト使用を開始するまでの間:これは私があなたの記事で見たものに基づいています

In [15]: 'a' in my_dict 
Out[15]: True 

In [16]: 'a*' in my_dict 
Out[16]: True 

In [17]: 'ap*' in my_dict 
Out[17]: True 

In [18]: 'b*' in my_dict 
Out[18]: True 

In [19]: 'bi*' in my_dict 
Out[19]: False 

を。 foo*以上をサポートする必要がある場合は、明らかにstartswithテストでは十分ではなく、正規表現を使用する必要があります。これはまたinをオーバーライドするだけです。my_dict['FOO*']のようなキーアクセスが必要な場合は、__getitem__とお友達もオーバーライドする必要があります。

お客様の要件に基づいてO(n)未満でこれを行う方法はありません。唯一の理由は、ハッシュのためにアクセス時間がO(1)であるため、キー全体がないとハッシュを取得できません。

1

あなたの目標を達成するには、少なくとも2つの方法があります。 例Aでは、メンバーがハッシュの一部であるかどうかを確認するためにクイッククエリが実行されます。一致が見つかると直ちに停止します。一方、例Bは、すべての一致する値が返されるのでより有用であることが判明するかもしれません。これにより、別のクエリを実行することなく、メンバーを処理するハッシュのその部分を処理することができます。

#! /usr/bin/env python3 


def main(): 
    """Demonstrate the usage of dict_contains and dict_search.""" 
    my_list = ['ist', 'out', 'ear', 'loopy'] 
    my_hash = {'a': 50, 'across': 14, 'ahash': 12, 'alist': 31, 'an': 73, 
       'and': 11, 'are': 2, 'as': 34, 'avoid': 82, 'be': 3, 
       'besides': 49, 'but': 45, 'can': 32, 'check': 51, 'come': 84, 
       'comparison': 40, 'custom': 61, 'dictionary': 58, 
       'different': 76, 'difficult': 85, 'do': 86, 'does': 13, 
       'entire': 37, 'every': 33, 'filled': 77, 'foobarbazz': 20, 
       'for': 42, 'fuzzy': 53, 'have': 30, 'how': 36, 'however': 68, 
       'i': 74, 'if': 43, 'implement': 62, 'in': 57, 'information': 46, 
       'is': 71, 'it': 83, 'like': 64, 'list': 55, 'looping': 70, 
       'makes': 63, 'match': 16, 'matches': 1, 'member': 29, 
       'members': 78, 'method': 7, 'might': 6, 'most': 28, 'my': 38, 
       'name': 18, 'naming': 41, 'of': 52, 'on': 17, 'oop': 35, 
       'operator': 21, 'over': 19, 'overload': 27, 'own': 72, 
       'reasons': 79, 'redefine': 10, 'research': 22, 'same': 48, 
       'search': 75, 'see': 5, 'situation': 39, 'so': 87, 'sounds': 24, 
       'straightforward': 69, 'stuff': 15, 'such': 66, 'that': 47, 
       'the': 56, 'then': 54, 'things': 81, 'think': 67, 'this': 59, 
       'to': 9, 'very': 0, 'want': 23, 'way': 60, 'what': 44, 
       'whole': 26, 'with': 8, 'without': 65, 'works': 4, 'would': 25, 
       'yet': 80} 
    # Example A 
    for member in my_list: 
     if dict_contains(my_hash, member): 
      print('Found:', member) 
    # Example B 
    for member in my_list: 
     match = dict_search(my_hash, member) 
     if match: 
      print('Query with', member, 'resulted in', match) 
     else: 
      print('Searching with', member, 'failed miserably') 


def dict_contains(self, needle): 
    """Check if search term can be found in any key of the given dict.""" 
    return any(needle in haystack for haystack in self) 


def dict_search(self, pattern): 
    """Return the dict's subset where the search term is found in the key.""" 
    return {key: value for key, value in self.items() if pattern in key} 


if __name__ == '__main__': 
    main() 
関連する問題