Find an element in a list with tuple in Python
<p>I have a little complicated data and want to find specific element with <em>key</em> tuple. <em>target</em> tuple is a little different from <em>key</em>, because it has an <em>id</em> property. So I cannot use <strong><em>key in target</em></strong>.</p>

<p>So what's the best way to implement smart searching in this case?</p>

<pre><code>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": ()}
</code></pre>

<p>I want to implement <em>find</em> method to extract expected slot like below.</p>

<pre><code>In []: find(targets, key)
Out[]: {'id': 2, 'X': (1,), 'Y': (5, 7), 'Z': ()}
</code></pre>

<p>If the key-value pairs must match exactly, you can use <a href="https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects" rel="nofollow"><em>Dictionary view objects</em></a> to treat the key-value pairs as <em>sets</em>. You want to find a <a href="https://docs.python.org/2/library/stdtypes.html#set.issubset" rel="nofollow"><em>strict subset</em></a>:</p>

<pre><code>def find(targets, key):
    for target in targets:
        if key.items() &lt; target.items():
            return target
</code></pre>

<p>This finds the <em>first</em> match only.</p>

<p>You could turn this into a one-liner:</p>

<pre><code>next((target for target in targets if key.items() &lt; target.items()), None)
</code></pre>

<p>If you must produce <strong>all</strong> matches, you can replace <code>return</code> with <code>yield</code> in the above method to turn it into a generator, or you could use a list comprehension:</p>

<pre><code>[target for target in targets if key.items() &lt; target.items()]
</code></pre>

<p>The above uses Python 3 syntax. In Python 2, dictionary views are available through the special <code>.viewkeys()</code>, <code>.viewvalues()</code> and <code>.viewitems()</code> methods, so add in <code>view</code> to the method name:</p>

<pre><code>def find(targets, key):
    # Python 2 version
    for target in targets:
        if key.viewitems() &lt; target.viewitems():
            return target
</code></pre>

<p>Demo (on Python 3):</p>

<pre><code>&gt;&gt;&gt; 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)},
... ]
&gt;&gt;&gt; key = {"X": (1,), "Y": (5, 7), "Z": ()}
&gt;&gt;&gt; def find(targets, key):
...     for target in targets:
...         if key.items() &lt; target.items():
...             return target
...
&gt;&gt;&gt; find(targets, key)
{'Y': (5, 7), 'X': (1,), 'Z': (), 'id': 2}
&gt;&gt;&gt; next((target for target in targets if key.items() &lt; target.items()), None)
{'Y': (5, 7), 'X': (1,), 'Z': (), 'id': 2}
&gt;&gt;&gt; [target for target in targets if key.items() &lt; target.items()]
[{'Y': (5, 7), 'X': (1,), 'Z': (), 'id': 2}]
</code></pre>

python tuples