Find in which of multiple sets a value belongs to
<p>I have several sets of values, and need to check in which of some of them a given value is located, and return the name of that set.</p>

<pre><code>value = 'a'
set_1 = {'a', 'b', 'c'}
set_2 = {'d', 'e', 'f'}
set_3 = {'g', 'h', 'i'}
set_4 = {'a', 'e', 'i'}
</code></pre>

<p>I'd like to check if value exists in sets 1-3, without including set_4 in the method, and return the set name. So something like:</p>

<pre><code>find_set(value in set_1, set_2, set_3)
</code></pre>

<p>should return</p>

<pre><code>set_1
</code></pre>

<p>Maybe some neat lambda function? I tried </p>

<pre><code>w = next(n for n,v in filter(lambda t: isinstance(t[1],set), globals().items()) if value in v)
</code></pre>

<p>from <a href="http://stackoverflow.com/questions/34783084/find-if-value-exists-in-multiple-lists">Find if value exists in multiple lists</a> but that approach checks ALL local/global sets. That won't work here, because the value can exist in several of them. I need to be able to specify in which sets to look.</p>

<p><em>Don't</em> use an ugly hackish lambda which digs in <code>globals</code> so you can get a name; that will confuse anyone reading your code including yourself after a few weeks :-).</p>

<p>You want to be able to get a name for sets you have defined, well, this is why we have dictionaries. Make a dictionary out of your sets and then you can create handy/readable set/list comprehensions to get what you want in a compact readable fashion:</p>

<pre><code>&gt;&gt;&gt; d = {'set_1': set_1, 'set_2': set_2, 'set_3': set_3, 'set_4': set_4}
</code></pre>

<p>To catch all sets in which <code>'a'</code> is located:</p>

<pre><code>&gt;&gt;&gt; {name for name, items in d.items() if 'a' in items}
{'set_1', 'set_4'}
</code></pre>

<p>To exclude some name add another the required clause to the <code>if</code> for filtering:</p>

<pre><code>&gt;&gt;&gt; {name for name, items in d.items() if 'a' in items and name != 'set_4'}
{'set_1'}
</code></pre>

<p>You can of course factor this into a function and be happy you'll be able to understand it if you bump into it in the future:</p>

<pre><code>def find_sets(val, *excludes, d=d):
    return {n for n, i in d.items() if val in i and n not in excludes}
</code></pre>

<p>This behaves in a similar way as the previous. <code>d=d</code> is probably not the way you want to do it, you'll probably be better of using some <code>**d</code> syntax for this.</p>

<hr>

<p>If you just want to get the first value, return the <code>next(comprehension)</code> from your function like this:</p>

<pre><code>def find_sets(val, *excludes, d=d):
    return next((n for n, i in d.items() if val in i and n not in excludes), '')
</code></pre>

<p>The <code>''</code> just indicates a default value to be returned if no elements are actually found, that is, when called with a value that isn't present, an empty string will be returned (subject to change according to your preferences):</p>

<pre><code>&gt;&gt;&gt; find_sets('1')
''
</code></pre>

python python-3.x set