The Second Element in A Dict Defined in Python keeps missing [duplicate] - python

This question already has answers here:
Boolean keys with other data types in dictionary
(3 answers)
Closed 4 years ago.
Python's version is 3.
In Python’s Interpreter in Mac's terminal (console), I tried defining a couple of Dicts but found that all the second elements in those Dicts were always missing. See the code below:
>>> dictOne = {True: 'real', 1: 'one', 'two': 2}
>>> dictOne
{True: 'one', 'two': 2}
>>> dictTwo = {1: 'one', True: 'real', 'two': 2}
>>> dictTwo
{1: 'real', 'two': 2}
>>> dictThree = {1: 'one', True: 'real', False: 'fake', 'two': 2}
>>> dictThree
{1: 'real', False: 'fake', 'two': 2}
Boolean and Integer values seem to interfere with each other. What happened?

True and 1 mean the same thing to Python. (True is basically bool(1), and True == 1 evaluates to True)
Python dicts don't allow duplicate keys, and True and 1 are considered duplicates.
EDIT: Alexandre Juma gave a nice explanation of this. Essentially, dict keys are hashed, and hash(1) and hash(True) return the same thing.

Related

Iterate over a list which contains dictionary names

I have a list which contains the names of different dictionaries. I want to iterate over those names and get the key and value of each of the dictionaries.
For eg:
ver=['one','two','three']
for v in ver:
for k,v in v.iteritems():
print k,v
where one, two, three are separate dictionaries. I need key, values from all the dictionaries.
But i am getting below error while doing this.
AttributeError("'str' object has no attribute 'iterkeys'",)
If, for some reason, you must use strings as you are doing. You can invoke globals() which keeps tracks over global variables or locals(), which keeps track of local variables like so:
>>> one = {'1': 1}
>>> two = {'2': 2}
>>> three = {'3': 3}
>>> ver = ['one', 'two', 'three']
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'a': 1, 'one': {'1': 1}, 'two': {'2': 2}, 'three': {'3': 3}, 'ver': ['one', 'two', 'three'], 'v': 'three'}
>>> for v in ver:
... print(globals()[v].items())
...
dict_items([('1', 1)])
dict_items([('2', 2)])
dict_items([('3', 3)])
You are mixing strings with the actual dicts.
Here is what you are actually looking for.
one = {1:9}
two = {'zz':34}
three = {}
ver = [one,two,three]
for v in ver:
for k,v in v.items():
print(k,v)
Variables in python are not enclosed with quotes. So instead define ver as:
ver = [one, two, three]
The most maintainable way to do what you require is to have them as keys of another dictionary, for example:
data = {
'one': {4:5, 'foo':'bar'},
'two': {1:'baz'},
'three': {'x':'y', 'a':'b'}
}
ver = ['one','two','three']
for x in ver:
for k,v in data[x].items():
print(k,v)
If you have them as separate variables, you could always start by constructing such a dictionary, as:
data = {
'one': one,
'two': two,
'three': three
}
Accessing variables dynamically by name is possible by use of the globals function, but in most cases this is less useful than organising your data in such a way as to make such an approach unnecessary.

Strict Comparison of Dictionaries in Python

I'm having a little bit of trouble comparing two similar dictionaries. I would like stricter comparison of the values (and probably keys).
Here's the really basic problem:
>>> {'a': True} == {'a': 1}
True
Similarly (and somewhat confusingly):
>>> {1: 'a'} == {True: 'a'}
True
This makes sense because True == 1. What I'm looking for is something that behaves more like is, but compares two possibly nested dictionaries. Obviously you can't use use is on the two dictionaries, because that will always return False, even if all of the elements are identical.
My current solution is to just use json.dumps to get a string representation of both and compare that.
>>> json.dumps({'a': True}, sort_keys=True) == json.dumps({'a': 1}, sort_keys=True)
False
But this only works if everything is JSON-serializable.
I also tried comparing all of the keys and values manually:
>>> l = {'a': True}
>>> r = {'a': 1}
>>> r.keys() == l.keys() and all(l[key] is r[key] for key in l.keys())
False
But this fails if the dictionaries have some nested structure. I figured I could write a recursive version of this to handle the nested case, but it seemed unnecessarily ugly and un-pythonic.
Is there a "standard" or simple way of doing this?
Thanks!
You were pretty close with JSON: Use Python's pprint module instead. This is documented to sort dictionaries in Python 2.5+ and 3:
Dictionaries are sorted by key before the display is computed.
Let's confirm this. Here's a session in Python 3.6 (which conveniently preserves insertion order even for regular dict objects):
Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> a = {2: 'two', 3: 'three', 1: 'one'}
>>> b = {3: 'three', 2: 'two', 1: 'one'}
>>> a
{2: 'two', 3: 'three', 1: 'one'}
>>> b
{3: 'three', 2: 'two', 1: 'one'}
>>> a == b
True
>>> c = {2: 'two', True: 'one', 3: 'three'}
>>> c
{2: 'two', True: 'one', 3: 'three'}
>>> a == b == c
True
>>> from pprint import pformat
>>> pformat(a)
"{1: 'one', 2: 'two', 3: 'three'}"
>>> pformat(b)
"{1: 'one', 2: 'two', 3: 'three'}"
>>> pformat(c)
"{True: 'one', 2: 'two', 3: 'three'}"
>>> pformat(a) == pformat(b)
True
>>> pformat(a) == pformat(c)
False
>>>
And let's quickly confirm that pretty-printing sorts nested dictionaries:
>>> a['b'] = b
>>> a
{2: 'two', 3: 'three', 1: 'one', 'b': {3: 'three', 2: 'two', 1: 'one'}}
>>> pformat(a)
"{1: 'one', 2: 'two', 3: 'three', 'b': {1: 'one', 2: 'two', 3: 'three'}}"
>>>
So, instead of serializing to JSON, serialize using pprint.pformat(). I imagine there may be some corner cases where two objects that you want to consider unequal nevertheless create the same pretty-printed representation. But those cases should be rare, and you wanted something simple and Pythonic, which this is.
You can test identity of all (key, value) pairs element-wise:
def equal_dict(d1, d2):
return all((k1 is k2) and (v1 is v2)
for (k1, v1), (k2, v2) in zip(d1.items(), d2.items()))
>>> equal_dict({True: 'a'}, {True: 'a'})
True
>>> equal_dict({1: 'a'}, {True: 'a'})
False
This should work with float, int, str and bool, but not other sequences or more complex objects.
Anyway, that's a start if you need it.
I think you are looking for something like this. However since you didn't provide example data I won't go into guessing what it could be
from boltons.itertools import remap
def compare(A, B): return A == B and type(A) == type(B)
dict_to_compare_against = { some dict }
def visit(path, key, value):
cur = dict_to_compare_against
for i in path:
cur = cur[i]
if not compare(cur, value):
raise Exception("Not equal")
remap(other_dict, visit=visit)
You can use isinstance() to delineate between a regular dictionary entry and a nested dictionary entry. This way you can iterate through using is to compare strictly, but also check when you need to dive down a level into the nested dictionary.
https://docs.python.org/3/library/functions.html#isinstance
myDict = {'a': True, 'b': False, 'c': {'a': True}}
for key, value in myDict.items():
if isinstance(value, dict):
# do what you need to do....
else:
# etc...

Sorting identical keys in a dictionary [duplicate]

This question already has answers here:
How can one make a dictionary with duplicate keys in Python?
(9 answers)
Closed 6 years ago.
I just started learning python and was wondering if its possible to pair two identical keys?
example:
my_dict= {1:a,3:b,1:c}
and I want to make a new dict, something like this:
new_dict= {1:{a,c},3:{b}}
thanks for the help
You can't have identical keys, that is the definition of dictionary. As soon as you add again the same key, the previous entry is deleted
You cannot have repeated dictionary keys in python.
From what I understand, you're trying to combine the two dictionaries. Given that you cannot have same keys in a dictionary, I'll suppose you have two distinct dictionaries you'd like to combine to obtain your combination.
Ex:
dic1 = {'a': 1, 'b': 2, 'c': 3}
dic2 = {'c': 4, 'd': 5, 'e': 6}
And the combination would produce:
{'a': {1}, 'b': {2}, 'c':{3, 4}, 'd': {4}, 'e': {6}}
You could use this Example:
from itertools import chain
from collections import defaultdict
dic1 = {'A': 1, 'B': 2, 'C': 3}
dic2 = {'C': 4, 'D': 5, 'E': 6}
dic = defaultdict(set)
for k, v in chain(dic1.items(), dic2.items()):
dic[k].add(v)
print(dict(dic))
Something to note:
'dic' is not exactly a dict(), it's of type 'defaultdict', but you can do dict(dic) to make it so.
You could instead of using set, use list in the defaultdict() argument and have a dictionary as so:
{'a': [1], 'b': [2], 'c':[3, 4], 'd': [4], 'e': [6]}
But to do so, dic[k].append(v) would be used in the for loop. You add items to sets, append to lists.
Dictionaries in Python, or any hash-able type for that matter, will not allow duplicate keys. If two duplicate keys are found in a dictionary, the key farthest in the dictionary will be persevered. This behavior can be obsevered first hand:
>>> my_dict= {1:'a',3:'b',1:'c'}
>>> my_dict
{1: 'c', 3: 'b'}
>>> my_dict= {1:'c',3:'b',1:'a'}
>>> my_dict
{1: 'a', 3: 'b'}
>>>
The Python documentation for dict()s touches on this matter:
It is best to think of a dictionary as an unordered set of key: value pairs, with the requirement that the keys are unique (within one dictionary).[...].
(emphasis mine)

Python dict value query without iterating [duplicate]

I have the following dictionary in python:
d = {'1': 'one', '3': 'three', '2': 'two', '5': 'five', '4': 'four'}
I need a way to find if a value such as "one" or "two" exists in this dictionary.
For example, if I wanted to know if the index "1" existed I would simply have to type:
"1" in d
And then python would tell me if that is true or false, however I need to do that same exact thing except to find if a value exists.
>>> d = {'1': 'one', '3': 'three', '2': 'two', '5': 'five', '4': 'four'}
>>> 'one' in d.values()
True
Out of curiosity, some comparative timing:
>>> T(lambda : 'one' in d.itervalues()).repeat()
[0.28107285499572754, 0.29107213020324707, 0.27941107749938965]
>>> T(lambda : 'one' in d.values()).repeat()
[0.38303399085998535, 0.37257885932922363, 0.37096405029296875]
>>> T(lambda : 'one' in d.viewvalues()).repeat()
[0.32004380226135254, 0.31716084480285645, 0.3171098232269287]
EDIT: And in case you wonder why... the reason is that each of the above returns a different type of object, which may or may not be well suited for lookup operations:
>>> type(d.viewvalues())
<type 'dict_values'>
>>> type(d.values())
<type 'list'>
>>> type(d.itervalues())
<type 'dictionary-valueiterator'>
EDIT2: As per request in comments...
>>> T(lambda : 'four' in d.itervalues()).repeat()
[0.41178202629089355, 0.3959040641784668, 0.3970959186553955]
>>> T(lambda : 'four' in d.values()).repeat()
[0.4631338119506836, 0.43541407585144043, 0.4359898567199707]
>>> T(lambda : 'four' in d.viewvalues()).repeat()
[0.43414998054504395, 0.4213531017303467, 0.41684913635253906]
In Python 3, you can use
"one" in d.values()
to test if "one" is among the values of your dictionary.
In Python 2, it's more efficient to use
"one" in d.itervalues()
instead.
Note that this triggers a linear scan through the values of the dictionary, short-circuiting as soon as it is found, so this is a lot less efficient than checking whether a key is present.
Python dictionary has get(key) function
>>> d.get(key)
For Example,
>>> d = {'1': 'one', '3': 'three', '2': 'two', '5': 'five', '4': 'four'}
>>> d.get('3')
'three'
>>> d.get('10')
None
If your key does not exist, then it will return None value.
foo = d[key] # raise error if key doesn't exist
foo = d.get(key) # return None if key doesn't exist
Content relevant to versions less than 3.0 and greater than 5.0.
Use dictionary views:
if x in d.viewvalues():
dosomething()..
Different types to check the values exists
d = {"key1":"value1", "key2":"value2"}
"value10" in d.values()
>> False
What if list of values
test = {'key1': ['value4', 'value5', 'value6'], 'key2': ['value9'], 'key3': ['value6']}
"value4" in [x for v in test.values() for x in v]
>>True
What if list of values with string values
test = {'key1': ['value4', 'value5', 'value6'], 'key2': ['value9'], 'key3': ['value6'], 'key5':'value10'}
values = test.values()
"value10" in [x for v in test.values() for x in v] or 'value10' in values
>>True
You can use this:
d = {'1': 'one', '3': 'three', '2': 'two', '5': 'five', '4': 'four'}
print("one" in d.values)
Or you can use any function:
print(any([True for i,j in d1.items() if j == "one"]))
In Python 3 you can use the values() function of the dictionary. It returns a view object of the values. This, in turn, can be passed to the iter function which returns an iterator object. The iterator can be checked using in, like this,
'one' in iter(d.values())
Or you can use the view object directly since it is similar to a list
'one' in d.values()

Accessing values nested within dictionaries

I have a dictionary which contains dictionaries, which may also contain dictionaries, e.g.
dictionary = {'ID': 0001, 'Name': 'made up name', 'Transactions':
{'Transaction Ref': 'a1', 'Transaction Details':
{'Bill To': 'abc', 'Ship To': 'def', 'Product': 'Widget A'
...} ...} ... }
Currently I'm unpacking to get the 'Bill To' for ID 001, 'Transaction Ref' a1 as follows:
if dictionary['ID'] == 001:
transactions = dictionary['Transactions']
if transactions['Transaction Ref'] == 'a1':
transaction_details = transactions['Transaction Details']
bill_to = transaction_details['Bill To']
I can't help but think this is is a little clunky, especially the last two lines - I feel like something along the lines of the following should work:
bill_to = transactions['Transaction Details']['Bill To']
Is there a simpler approach for drilling down into nested dictionaries without having to unpack into interim variables?
You can use something like this:
>>> def lookup(dic, key, *keys):
... if keys:
... return lookup(dic.get(key, {}), *keys)
... return dic.get(key)
...
>>> d = {'a':{'b':{'c':5}}}
>>> print lookup(d, 'a', 'b', 'c')
5
>>> print lookup(d, 'a', 'c')
None
Additionally, if you don't want to define your search keys as individual parameters, you can just pass them in as a list like this:
>>> print lookup(d, *['a', 'b', 'c'])
5
>>> print lookup(d, *['a', 'c'])
None
bill_to = transactions['Transaction Details']['Bill To']
actually works. transactions['Transaction Details'] is an expression denoting a dict, so you can do lookup in it. For practical programs, I would prefer an OO approach to nested dicts, though. collections.namedtuple is particularly useful for quickly setting up a bunch of classes that only contain data (and no behavior of their own).
There's one caveat: in some settings, you might want to catch KeyError when doing lookups, and in this setting, that works too, it's hard to tell which dictionary lookup failed:
try:
bill_to = transactions['Transaction Details']['Bill To']
except KeyError:
# which of the two lookups failed?
# we don't know unless we inspect the exception;
# but it's easier to do the lookup and error handling in two steps
Following is another way of accessing nested dictionaries
>>> dbo={'m':{'d':{'v':{'version':1}}}}
>>> name='m__d__v__version' # it'll refer to 'dbo['m']['d']['v']['version']', '__' is the separator
>>> version = reduce(dict.get, name.split('__'), dbo)
>>> print version
1
>>>
Here, variable 'name' refers to 'dbo['m']['d']['v']['version']', which seems much shorter and neat.
This method will not throw KeyError. If a key is not found then you'll get 'None'.
Ref.: http://code.activestate.com/recipes/475156-using-reduce-to-access-deeply-nested-dictionaries/
You can access nested dictionaries with a tuple using NestedDict.
>>> from ndicts.ndicts import NestedDict
>>> nested_dict = {"a": {"a": 0, "b": 1},
... "b": {"a": 2, "b": 3}}
>>> nd = NestedDict(nested_dict)
>>> nd["a", "a"]
0
>>> nd["b", "a"]
2
>>> nd["a"]
{"a": 0, "b": 1}
To install ndicts:
pip install ndicts

Categories