1

I'm using frozensets to keep the keys of my dictionary to take an advantage of union, difference and intersection operations. But when I'm trying to retrieve values by keys from the dictionary through dict.get() it yields a None value.

newDict = {'a': 1, 'b': 2, 'c': 3, 'd': True}
stKeys = set(newDict)
stA = frozenset('a')
stB = frozenset('b')
stC = frozenset('c')
stD = frozenset('d')

print(stKeys)
print(newDict.get(stA & stKeys))
print(newDict.get(stB & stKeys))
print(newDict.get(stC & stKeys))
print(newDict.get(stD & stKeys))

Produce:

>>>None
>>>None
>>>None
>>>None

And even:

print(newDict.get(stA))
print(newDict.get(stB))
print(newDict.get(stC))
print(newDict.get(stD))

Produce:

>>>None
>>>None
>>>None
>>>None

How to retrieve values from the dictionary if your keys are in frozensets?

Thanks to Martijn Pieters! The answer is DVO (Dictionary view objects) and the generator expression if you want to add the result to a list()

Michael
  • 340
  • 3
  • 13

3 Answers3

2

You can use dictionary view objects if you want to look for set intersections:

for key in newDict.viewkeys() & stA:
    # all keys that are in the intersection of stA and the dictionary

In Python 3, returning dictionary views is the default; you can use newDict.keys() here:

for key in newDict.keys() & stA:
    # all keys that are in the intersection of stA and the dictionary

Demo on Python 3:

>>> newDict = {'a': 1, 'b': 2, 'c': 3, 'd': True}
>>> stA = frozenset('a')
>>> stB = frozenset('b')
>>> stC = frozenset('c')
>>> stD = frozenset('d')
>>> newDict.keys() & stA
{'a'}
>>> for key in newDict.keys() & stA:
...     print(newDict[key])
... 
1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • yes, DVO (dictionary view objects) do the magic, but the result of the intersection is a new set again :( So I can't append this result to my list: `aList.append(newDict.viewkeys() & stA)` – Michael Apr 05 '15 at 18:39
  • @Michael: you can *extend* your list: `aList.extend(newDict.viewkeys() & stA)`. Set intersections always produce 0 or more elements, not just 1. – Martijn Pieters Apr 05 '15 at 18:45
  • yes but it will be a dictionary key not the dictionary value! My question marked out by the bold font was: **How to retrieve values from the dictionary....?** To be more clear you can't write `aList.append(newDict.get(newDict.viewkeys() &stA))` and `aList.extend(newDict.get(newDict.viewkeys() &stA))` is also impossible :( It is all I want. – Michael Apr 05 '15 at 19:08
  • `aList.append(newDict[newDict.viewkeys() & stA])` retrieving value by the key from the dictionary instead of dict.get() method doesn't work too ( – Michael Apr 05 '15 at 19:15
  • You'd use a generator expression: `aList.extend(newDict[k] for k in newDict.viewkeys() & setA)`. – Martijn Pieters Apr 05 '15 at 19:27
  • yeeeew! Oh my god! Man you've saved the world and made my day.. It would take me a week If I had been trying to solve this issue alone. **Thanks a million!** – Michael Apr 05 '15 at 19:56
1

To create frozen set keys you need to actually create frozen sets and use them as keys:

newDict = {
    frozenset('a'): 1,
    frozenset('b'): 2,
    frozenset('c'): 3,
    frozenset('d'): True
}

Test:

>>> {frozenset('a'):1}[frozenset('a')]
1
Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
  • My example above is simplified version (prototype) of the real code. In my case I do not create the dictionary, I'm receiving it from the function argument (command line): `def foo(var, **kwDict)`. So I can't use your advice but anyway thanks too. – Michael Apr 05 '15 at 18:50
0

You actually can do what you are trying to do, at least in 3.6.1 and I suspect 2.7.x as well:

newDict = {frozenset('a'): 1, frozenset('b'): 2, frozenset('c'): 3, 'd': True}
stKeys = set(newDict)
stA = frozenset('a')
print(stA)
stB = frozenset('b')
stC = frozenset('c')
stD = 'd'

print(newDict[stA])
print(newDict[stB])
print(newDict[stC])
print(newDict[stD])

Output:

frozenset({'a'})
1
2
3
True

The problem seems to be that the key was being assigned as a string object and not a frozenset, yet the search was set to look for a frozenset.

Shanemeister
  • 667
  • 7
  • 13