2016-09-12 18 views
-3

少し複雑なデータがあり、特定の要素をキータプルで検索したい。 ターゲットタプルは、idプロパティを持つため、キーと少し異なります。だからキーをターゲットに使用することはできませんリスト内のタプル付き要素をPythonで見つけよう

この場合、スマート検索を実装する最良の方法は何ですか?

targets = [ 
    {"id": 0, "X":(), "Y":(), "Z":() }, 
    {"id": 1, "X": (1,), "Y": (5,), "Z":()}, 
    {"id": 2, "X": (1,), "Y": (5, 7), "Z":()}, 
    {"id": 3, "X": (2,), "Y": (5, 7), "Z": (1,)}, 
    {"id": 4, "X": (1, 2), "Y": (5, 7), "Z": (1,)}, 
    {"id": 5, "X": (1, 2), "Y": (5, 7), "Z": (1,3)}, 
] 

key = {"X": (1,), "Y": (5, 7), "Z":()} 

私は以下のように予想されるスロットを抽出する方法を見つける実装したいです。キーと値のペアが正確に一致しなければならない場合

In []: find(targets, key) 
Out[]: {'id': 2, 'X': (1,), 'Y': (5, 7), 'Z':()} 
+3

'(1 ) 'はタプルではありません。それはちょうど単一の整数です。 '()'のみのグループは、タプルを生成するために*(カンマ*)が必要です: '(1、)'。 –

+0

これを行うには強引な方法があります。何を試しましたか? –

+0

まだ何か試しましたか?これは本当に辞書の質問の値を他の人が検索することと変わりません。解決策は、ブルートフォース(あらゆる辞書のすべての値を検索する)、または再使用して維持するインデックスを構築し、それを逆方向にマップすることです。 –

答えて

2

、あなたはセットように、キーと値のペアを治療するためのDictionary view objectsを使用することができます。あなたはstrict subsetを見つけたい:

def find(targets, key): 
    for target in targets: 
     if key.items() < target.items(): 
      return target 

これだけ最初一致を見つけました。あなたは可能性があり、あなたがすべてマッチを生成しなければならない場合は、発電機にそれを回すために、上記の方法でyieldreturnを置き換えることができ

next((target for target in targets if key.items() < target.items()), None) 

、または:あなたはワンライナーにこれを回すことができる

[target for target in targets if key.items() < target.items()] 

上記のPython 3の構文を使用します。リストの内包表記を使用します。パイソン2において、ディクショナリ・ビューは、特別.viewkeys().viewvalues().viewitems()方法により入手可能であるので、メソッド名にviewに追加:(Pythonの3上の)

def find(targets, key): 
    # Python 2 version 
    for target in targets: 
     if key.viewitems() < target.viewitems(): 
      return target 

デモ:

>>> targets = [ 
...  {"id": 0, "X":(), "Y":(), "Z":() }, 
...  {"id": 1, "X": (1,), "Y": (5,), "Z":()}, 
...  {"id": 2, "X": (1,), "Y": (5, 7), "Z":()}, 
...  {"id": 3, "X": (2,), "Y": (5, 7), "Z": (1,)}, 
...  {"id": 4, "X": (1, 2), "Y": (5, 7), "Z": (1,)}, 
...  {"id": 5, "X": (1, 2), "Y": (5, 7), "Z": (1,3)}, 
... ] 
>>> key = {"X": (1,), "Y": (5, 7), "Z":()} 
>>> def find(targets, key): 
...  for target in targets: 
...   if key.items() < target.items(): 
...    return target 
... 
>>> find(targets, key) 
{'Y': (5, 7), 'X': (1,), 'Z':(), 'id': 2} 
>>> next((target for target in targets if key.items() < target.items()), None) 
{'Y': (5, 7), 'X': (1,), 'Z':(), 'id': 2} 
>>> [target for target in targets if key.items() < target.items()] 
[{'Y': (5, 7), 'X': (1,), 'Z':(), 'id': 2}] 
+0

ご意見ありがとうございます。あなたのコードを確認できました。しかし、 "Y"の値の順序が1と異なるため、(ターゲット、{"X":(1、)、 "Y":(7,5)、 "Z":()})は機能しません。注文を無視する方法はありますか? – jef

+0

@jef:はい、 '' Y''タプルの順序が異なります。タプルで注文*事項*。順序を無視する必要がある場合は、タプルの代わりに 'set'または' frozenset'オブジェクトを保存してください。 –

+0

@jef: 'set()'の例はhttp://pastebin.com/Jerxtertを参照してください。 –

関連する問題