Anil
Anil

Reputation: 1369

Union over iterable elements in set comprehension

I have a list of unique keys and I want to find the unique character set used to compose those keys

idx_keys = [
    "1996/a/50/18_supp__323:5",
    "1996/a/50/18_supp__326:1",
    "1996/a/50/18_supp__368:2",
    "1996/a/50/18_supp__907:1",
    "1996/a/c_2/51/sr_37_164:1",
]

I can do this

chars = set()
for k in idx_keys:
    chars = chars.union(k)

print(chars)
print(f"{'-' in chars = }")  # -> False
print(f"{'_' in chars = }")  # -> True

But I can't do this

print({set(k) for chars in idx_keys}) # -> TypeError: unhashable type: 'set'

Can someone explain how I can do this more neatly. Obviously the logic here applies to getting the union of any nested iterable, not just a list of strings.

Caveat: I know doing this inside a set comprehension may not be ideal from a readability perspective, but humor me. I think I saw something similar with the walrus operator and would like to see what a compact solution looks like, also because it might be faster.

Upvotes: 0

Views: 111

Answers (3)

funnydman
funnydman

Reputation: 11396

Or fixing your solutions and then chaining result:

idx_keys = [
    "1996/a/50/18_supp__323:5",
    "1996/a/50/18_supp__326:1",
    "1996/a/50/18_supp__368:2",
    "1996/a/50/18_supp__907:1",
    "1996/a/c_2/51/sr_37_164:1",
]


print(set(itertools.chain(*{frozenset(chars) for chars in idx_keys})))

Output:

{'7', '8', '1', 'p', '_', ':', 'c', '5', '3', 'a', '0', 's', '2', 'r', '4', '9', 'u', '/', '6'}

Upvotes: 0

a_guest
a_guest

Reputation: 36339

You can use functools.reduce and operator.or_ to achieve a similar result:

from functools import reduce
import operator as op

chars = reduce(op.or_, map(set, idx_keys))

Upvotes: 1

Ecir Hana
Ecir Hana

Reputation: 11528

For that to work, you would need two nested loops like:

idx_keys = [
    "1996/a/50/18_supp__323:5",
    "1996/a/50/18_supp__326:1",
    "1996/a/50/18_supp__368:2",
    "1996/a/50/18_supp__907:1",
    "1996/a/c_2/51/sr_37_164:1",
]

print({char for key in idx_keys for char in key})

As for the error, set() can only contain non-mutable items and set() is mutable (as opposed to frozenset()).

Upvotes: 1

Related Questions