Python: get key of index in dictionary [duplicate] - python

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inverse dictionary lookup - Python
reverse mapping of dictionary with Python
How do i get key of index in dictionary?
For example like:
i = {'a': 0, 'b': 1, 'c': 2}
so if i want to get key of i[0], it will return 'a'

You could do something like this:
i={'foo':'bar', 'baz':'huh?'}
keys=i.keys() #in python 3, you'll need `list(i.keys())`
values=i.values()
print keys[values.index("bar")] #'foo'
However, any time you change your dictionary, you'll need to update your keys,values because dictionaries are not ordered in versions of Python prior to 3.7. In these versions, any time you insert a new key/value pair, the order you thought you had goes away and is replaced by a new (more or less random) order. Therefore, asking for the index in a dictionary doesn't make sense.
As of Python 3.6, for the CPython implementation of Python, dictionaries remember the order of items inserted. As of Python 3.7+ dictionaries are ordered by order of insertion.
Also note that what you're asking is probably not what you actually want. There is no guarantee that the inverse mapping in a dictionary is unique. In other words, you could have the following dictionary:
d={'i':1, 'j':1}
In that case, it is impossible to know whether you want i or j and in fact no answer here will be able to tell you which ('i' or 'j') will be picked (again, because dictionaries are unordered). What do you want to happen in that situation? You could get a list of acceptable keys ... but I'm guessing your fundamental understanding of dictionaries isn't quite right.

Python dictionaries have a key and a value, what you are asking for is what key(s) point to a given value.
You can only do this in a loop:
[k for (k, v) in i.iteritems() if v == 0]
Note that there can be more than one key per value in a dict; {'a': 0, 'b': 0} is perfectly legal.
If you want ordering you either need to use a list or a OrderedDict instance instead:
items = ['a', 'b', 'c']
items.index('a') # gives 0
items[0] # gives 'a'

By definition dictionaries are unordered, and therefore cannot be indexed. For that kind of functionality use an ordered dictionary. Python Ordered Dictionary

Related

What determines if a dictionarie's items are ordered or not? [duplicate]

This question already has answers here:
How to keep keys/values in same order as declared?
(13 answers)
Closed 3 years ago.
I've started a python crash course and this is an excerpt of it, pertaining to dictionaries
myDict = {'One':1.35, 2.5:'Two Point Five', 3:'+', 7.9:2}
# print the entire dictionary
print(myDict)
You’ll get {2.5: 'Two Point Five', 3: '+', 'One': 1.35, 7.9: 2}
Note that items in a dictionary are not stored in the same order as the way you declare them.
I've replicated that, and in my case the items are printed as I declared them. Why am I getting a different result?
My output:
myDict = {'One':1.35, 2.5:'Two Point Five', 3:'+', 7.9:2}
#print the entire dictionary
print(myDict)
Output: {'One': 1.35, 2.5: 'Two Point Five', 3: '+', 7.9: 2}
Dictionaries differ from lists as they can't be indexed like them and furthermore, they are "unsorted". However, in newer versions of python, you get the same order as you used to set up the dictionary. If the course you watched used an older version of python, it should explain why the result was random.
Python dictionaries are ordered by design since python 3.7 (sorting if it makes sense). If you use python 3.6 or lower, you can order your dictionary by storing its keys in a list, sort the list and loop through the list.
dictionary always follows a key(always string format), value(any format) pair it doesn't know about order and unorders you always fetch data from the dictionary using the key name.
You can order your dictionary, but it based on the value of your dictionary, not key and your key order will be changed according to your new order values.

can I compare the keys of two dictionaries that are not in the same order?

I apologize this must be a basic question for using dictionaries. I'm learning python, and the objective I have is to compare two dictionaries and recover the Key and Value entries from both entries that are identical. I understand that the order in dictionaries is not relevant like if one is working with a list. But I adopted a code to compare my dictionaries and i just wanted to make sure that the order of the dictionaries does not matter.
The code I have written so far is:
def compare_dict(first,second):
with open('Common_hits_python.txt', 'w') as file:
for keyone in first:
for keytwo in second:
if keytwo == keyone:
if first[keyone] == second[keytwo]:
file.write(keyone + "\t" + first[keyone] + "\n")
Any recommendations would be appreciated. I apologize for the redundany in the code above. But if someone could confirm that comparing two dictionaries this way does not require the key to be in the same order would great. Other ways of writing the function would be really appreciated as well.
Since you loop over both dictionaries and compare all the combinations, no, order doesn't matter. Every key in one dictionary is compared with every key in the other dictionary, eventually.
It is not a very efficient way to test for matching keys, however. Testing if a key is present is as simple as keyone in second, no need to loop over all the keys in second here.
Better still, you can use set intersections instead:
for key, value in first.viewitems() & second.viewitems():
# loops over all key - value pairs that match in both.
file.write('{}\t{}\n'.format(key, value))
This uses dictionary view objects; if you are using Python 3, then you can use first.items() & second.items() as dictionaries there return dictionary views by default.
Using dict.viewitems() as a set only works if the values are hashable too, but since you are treating your values as strings when writing to the file I assumed they were.
If your values are not hashable, you'll need to validate that the values match, but you can still use views and intersect just the keys:
for key in first.viewkeys() & second.viewkeys():
# loops over all keys that match in both.
if first[key] == second[key]:
file.write('{}\t{}\n'.format(key, first[key]))
Again, in Python 3, use first.keys() & second.keys() for the intersection of the two dictionaries by keys.
Your way of doing it is valid. As you look through both lists, the order of the dictionaries does not matter.
You could do this instead, to optimize your code.
for keyone in first:
if keyone in second: # returns true if keyone is present in second.
if first[keyone] == second[keyone]:
file.write(keyone + "\t" + first[keyone] + "\n")
The keys of a dictionary are effectively a set, and Python already has a built-in set type with an efficient intersection method. This will produce a set of keys that are common to both dictionaries:
dict0 = {...}
dict1 = {...}
set0 = set(dict0)
set1 = set(dict1)
keys = set0.intersection(set1)
Your goal is to build a dictionary out of these keys, which can be done with a dictionary comprehension. It will require a condition to keep out the keys that have unequal values in the two original dictionaries:
new_dict = {k: dict0[k] for k in keys if dict0[k] == dict1[k]}
Depending on your intended use for the new dictionary, you might want to copy or deepcopy the old dictionary's values into the new one.

Join dictionary item, keys [duplicate]

This question already has answers here:
Iterating over dictionaries using 'for' loops
(15 answers)
Closed 8 years ago.
Please see below code snippet for join method (used Python 2.7.2):
iDict={'1_key':'abcd','2_key':'ABCD','3_key':'bcde','4_key':'BCDE'}
'--'.join(iDict)
Result shown as
'2_key--1_key--4_key--3_key'
Please comment why only keys are joined? Also the sequence is not in order.
Note - below are the individual methods.
'--'.join(iDict.values()) ==> 'ABCD--abcd--BCDE--bcde' ==> the sequence is not in order
'--'.join(iDict.keys()) ==> '2_key--1_key--4_key--3_key' ==> the sequence is not in orde
If you see the docs, you learn that iterating over dict returns keys.
You need to iterate over dict.items(), that it over tuples (key, value):
'--'.join(iDict.items())
If you need to have key AND value joined in one string, you need to explicitly tell Python how to do this:
'--'.join('{} : {}'.format(key, value) for key, value in iDict.items())
Python dictionaries are unordered (or rather, their order is arbitrary), and when you iterate on them, only the keys are returned:
>>> d = {'0':0, '1':1, '2':2, '3':3, '4':4}
>>> print(d)
{'4': 4, '1': 1, '0': 0, '3': 3, '2': 2}
If you need both keys and values, use iDict.items().
If you need ordering, use collections.OrderedDict.
Iteration over a dictionary only ever yields keys:
>>> list(iDict)
['2_key', '1_key', '4_key', '3_key']
See the dict() documentation:
iter(d)
Return an iterator over the keys of the dictionary. This is a shortcut for iterkeys().
Both list() and str.join() will call iter() on their arguments to iterate over the elements.
Dictionaries are unordered containers; their order stems from the underlying data structure and depends on the insertion and deletion history of the keys.
This is documented under dict.items():
CPython implementation detail: Keys and values are listed in an arbitrary order which is non-random, varies across Python implementations, and depends on the dictionary’s history of insertions and deletions.
Also see Why is the order in dictionaries and sets arbitrary?

Python and no obvious way to get a specific element from a dictionary

How come that I can easily do a for-loop in Python to loop through all the elements of a dictionary in the order I appended the elements but there's no obvious way to access a specific element? When I say element I'm talking about a key+value pair.
I've looked through what some basic tutorials on Python says on dictionaries but not a single one answers my question, I can't find my answer in docs.python.org either.
According to:
accessing specific elements from python dictionary (Senderies comment) a dict is supposed to be unordered but then why does the for-loop print them in the order I put them in?
You access a specific element in a dictionary by key. That's what a dictionary is. If that behavior isn't what you want, use something other than a dictionary.
a dict is supposed to be unordered but then why does the for-loop print them in the order I put them in?
Coincidence: basically, you happened to put them in in the order that Python prefers. This isn't too hard to do, especially with integers (ints are their own hashes and will tend to come out from a dict in ascending numeric order, though this is an implementation detail of CPython and may not be true in other Python implementations), and especially if you put them in in numerical order to begin with.
"Unordered" really means that you don't control the order, and it may change due to various implementation-specific criteria, so you should not rely on it. Of course when you iterate over a dictionary elements come out in some order.
If you need to be able to access dictionary elements by numeric index, there are lots of ways to do that. collections.OrderedDict is the standard way; the keys are always returned in the order you added them, so you can always do foo[foo.keys()[i]] to access the ith element. There are other schemes you could use as well.
Python dicts are accessed by hashing the key. So if you have any sort of a sizable dict and things are coming out in the order you put them in, then it's time to start betting on the lottery!
my_dict = {}
my_dict['a'] = 1
my_dict['b'] = 2
my_dict['c'] = 3
my_dict['d'] = 4
for k,v in my_dict.items():
print k, v
yields:
a 1
c 3
b 2
d 4
d = {}
d['first'] = 1
d['second'] = 2
d['third'] = 3
print d
# prints {'seconds': 2, 'third': 3, 'first': 1}
# Hmm, just like the docs say, order of insertion isn't preserved.
print d['third']
# prints 3
# And there you have it: access to a specific element
If you want to iterate through the items in insertion order, you should be using OrderedDict. A regular dict is not guaranteed to do the same, so you're asking for trouble later if you rely on it to do so.
If you want to access a particular item, you should access it by its key using the [] operator or the get() method. That's the primary function of a dict, after all.
Result of the hashing of several values varies according the values:
sometimes the order seems to be kept: following example with d_one
generaly, the order is not kept: following example with d_two
Believing that the order is anyway kept is only because you are deceived by particuliar cases in which the order is apparently conserved
d_one = {}
for i,x in enumerate((122,'xo','roto',885)):
print x
d_one[x] = i
print
for k in d_one:
print k
print '\n=======================\n'
d_two = {}
for i,x in enumerate((122,'xo','roto','taratata',885)):
print x
d_two[x] = i
print
for k in d_two:
print k
result
122
xo
roto
885
122
xo
roto
885
=======================
122
xo
roto
taratata
885
122
taratata
xo
roto
885
By the way, what you call "elements of a dictionary' are commonly called 'items of the dictionary' ( hence the methods items() and iteritems() of a dictionary)

Why dictionary values aren't in the inserted order?

When i declare a list 1,2,3,4 and i do something with it , even just print i get back the same sequence 1,2,3,4.
But when i do anything with dictionaries , they always change number sequence , like it is being sorted in a twisted way i can't understand .
test1 = [4,1,2,3,6,5]
print test1
test2 = {"c":3,"a":1,"b":2,"d":4}
print test2
[4, 1, 2, 3, 6, 5]
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
How in the world did 'a' become the first element and 'c' , even if it alphabetically sorted the dictionary it should have been 1,2,3,4 or a,b,c,d not 1,3,2,4 . wT?F #!$!#$##!
So how do i print , get values from dictionary without changing the positions of the elements .?
Dictionaries in Python are unordered by definition. Use OrderedDict if you need the order in which values were inserted (it's available in Python 2.7 and 3.x).
dictionary sort order is undefined! Do not rely on it for anything. Look for a sorted dictionary if you really want a sorted dictionary, but usually you don't need one.
Examples:
python 2.7, it's built in to the collections module
Django has a SortedDict shipped with it
2.4-2.7 you can use the ordereddict module, you can pip install or easy_install it
Before you get so angry and frustrated, perhaps you should read about what a dictionary actually is and how it works:
http://docs.python.org/library/stdtypes.html#mapping-types-dict
Python dicts use a hash table as the underlying storage mechanism. That means that a hash key is generated from the key that you provide. There are no guarantees about ordering with these hash keys. The entries in a dictionary are fetched in sequential order of their location in the underlying hash table when you request values(), keys(), or items().
The advantage of using a hash table is that it is extremely fast. Unlike the map class from c++ which uses a red-black tree storage mechanism ( which is sorted by the raw keys ), a hash table doesn't constantly need to be restructured to keep it efficient. For more on hash tables, see:
http://en.wikipedia.org/wiki/Hash_table
Like the other posters have said, look up OrderedDict if you need to have a key-sorted dictionary.
Good Luck!
Clearly you know about lists. You can ask for the element at the ith index of a list. This is because lists are ordered.
>>> [1,2,3,4] == [1,4,3,2]
False
In this context, you can think of dictionaries, but where the index is the key. Therefore, two dictionaries are equal if the corresponding values of all keys in both dictionaries are the same (if one dictionary has keys that the other doesn't, then the two are not equal). Thus:
>>> {1:'a', 2:'b'} == {2:'b', 1:'a'}
True
Further Trivia
A dictionary does something called hashing on the keys of the dictionary so that when you ask for the value at a particular key (index), it can retrieve this value faster.
Hope this helps
Dictionaries are unsorted. This is well-documented. Do not rely on the ordering of dictionaries.
If you want to see the entries in order. something like:
test2 = {"c":3,"a":1,"b":2,"d":4}
ks = test2.keys()
ks.sort()
for key in ks:
print key + ':' + str(test2[key])
(cut,paste, season to taste)

Categories

Resources