Why dictionary values aren't in the inserted order? - python

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)

Related

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.

getting the key index in a Python OrderedDict?

I have a collections.OrderedDict with a list of key, value pairs. I would like to compute the index i such that the ith key matches a given value. For example:
food = OrderedDict([('beans',33),('rice',44),('pineapple',55),('chicken',66)])
I want to go from the key chicken to the index 3, or from the key rice to the index 1. I can do this now with
food.keys().index('rice')
but is there any way to leverage the OrderedDict's ability to look things up quickly by key name? Otherwise it seems like the index-finding would be O(N) rather than O(log N), and I have a lot of items.
I suppose I can do this manually by making my own index:
>>> foodIndex = {k:i for i,k in enumerate(food.keys())}
>>> foodIndex
{'chicken': 3, 'rice': 1, 'beans': 0, 'pineapple': 2}
but I was hoping there might be something built in to an OrderedDict.
Basically, no. OrderedDict gets its ability to look things up quickly by key name just by using a regular, unordered dict under the hood. The order information is stored separately in a doubly linked list. Because of this, there's no way to go directly from the key to its index. The order in an OrderedDict is mainly intended to be available for iteration; a key does not "know" its own order.
As others have pointed out, an OrderedDict is just a dictionary that internally remembers what order entries were added to it. However, you can leverage its ability to look-up things quickly by storing the desired index along with the rest of the data for each entry. Here's what I mean:
from collections import OrderedDict
foods = [('beans', 33), ('rice', 44), ('pineapple', 55), ('chicken', 66)]
food = OrderedDict(((v[0], (v[1], i)) for i, v in enumerate(foods))) # saves i
print(food['rice'][1]) # --> 1
print(food['chicken'][1]) # --> 3
The OrderedDict is a subclass of dict which has the ability to traverse its keys in order (and reversed order) by maintaining a doubly linked list. So it does not know the index of a key. It can only traverse the linked list to find the items in O(n) time.
Perusing the source code may be the most satisfying way to confirm that the index is not maintained by OrderedDict. You'll see that no where is an index ever used or obtained.

Python: get key of index in dictionary [duplicate]

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

How to print dictionary's values from left to right?

I have a dictionary:
a = {"w1": "wer", "w2": "qaz", "w3": "edc"}
When I try to print its values, they are printed from right to left:
>>> for item in a.values():
print item,
edc qaz wer
I want them to be printed from left to right:
wer qaz edc
How can I do it?
You can't. Dictionaries don't have any order you can use, so there's no concept of "left to right" with regards to dictionary literals. Decide on a sorting, and stick with it.
You can use collections.OrderedDict (python 2.7 or newer -- There's an ActiveState recipe somewhere which provides this functionality for python 2.4 or newer (I think)) to store your items. Of course, you'll need to insert the items into the dictionary in the proper order (the {} syntax will no longer work -- nor will passing key=value to the constructor, because as others have mentioned, those rely on regular dictionaries which have no concept of order)
Assuming you want them in alphabetical order of the keys, you can do something like this:
a = {"w1": "wer", "w2": "qaz", "w3": "edc"} # your dictionary
keylist = a.keys() # list of keys, in this case ["w3", "w2", "w1"]
keylist.sort() # sort alphabetically in place,
# changing keylist to ["w1", "w2", w3"]
for key in keylist:
print a[key] # access dictionary in order of sorted keys
as #IgnacioVazquez-Abrams mentioned, this is no such thing as order in dictionaries, but you can achieve a similar effect by using the ordered dict odict from http://pypi.python.org/pypi/odict
also check out PEP372 for more discussion and odict patches.
Dictionaries use hash values to associate values. The only way to sort a dictionary would look something like:
dict = {}
x = [x for x in dict]
# sort here
y = []
for z in x: y.append(dict[z])
I haven't done any real work in python in a while, so I may be a little rusty. Please correct me if I am mistaken.

Sorting a dictionary with lists as values, according to an element from the list

I want to sort a dictionary of lists, by third item in each list. It's easy enough sorting a dictionary by value when the value is just a single number or string, but this list thing has me baffled.
Example:
myDict = {'item1': [7, 1, 9], 'item2': [8, 2, 3], 'item3': [9, 3, 11] }
I want to be able to iterate through the dictionary in order of the third value in each list, in this case item2, item1 then item3.
Here is one way to do this:
>>> sorted(myDict.items(), key=lambda e: e[1][2])
[('item2', [8, 2, 3]), ('item1', [7, 1, 9]), ('item3', [9, 3, 11])]
The key argument of the sorted function lets you derive a sorting key for each element of the list.
To iterate over the keys/values in this list, you can use something like:
>>> for key, value in sorted(myDict.items(), key=lambda e: e[1][2]):
... print key, value
...
item2 [8, 2, 3]
item1 [7, 1, 9]
item3 [9, 3, 11]
You stated two quite different wants:
"What I want to do is sort a dictionary of lists ..."
"I want to be able to iterate through the dictionary in order of ..."
The first of those is by definition impossible -- to sort something implies a rearrangement in some order. Python dictionaries are inherently unordered. The second would be vaguely possible but extremely unlikely to be implemented.
What you can do is
Take a copy of the dictionary contents (which will be quite
unordered)
Sort that
Iterate over the sorted results -- and you already have two
solutions for that. By the way, the solution that uses "key" instead
of "cmp" is better; see sorted
"the third item in the list" smells like "the third item in a tuple" to me, and "e[1][2]" just smells :-) ... you may like to investigate using named tuples instead of lists; see named tuple factory
If you are going to be doing extract/sort/process often on large data sets, you might like to consider something like this, using the Python-supplied sqlite3 module:
create table ex_dict (k text primary key, v0 int, v1 int, v2 int);
insert into ex_dict values('item1', 7, 1, 9);
-- etc etc
select * from ex_dict order by v2;
As John Machlin said you can't actually sort a Python dictionary.
However, you can create an index of the keys which can be sorted in any order you like.
The preferred Python pattern (idiom) for sorting by any alternative criterium is called "decorate-sort-undecorate" (DSU). In this idiom you create a temporary list which contains tuples of your key(s) followed by your original data elements, then call the normal .sort() method on that list (or, in more recent versions of Python simply wrap your decoration in a called to the sorted() built-in function). Then you remove the "decorations."
The reason this is generally preferred over passing comparison function to the .sort() method is that Python's built-in default sorting code (compiled C in the normal C Python) is very fast and efficient in the default case, but much, much slower when it has to call Python object code many, many times in the non-default case. So it's usually far better to iterate over the data creating data structures which can be passed to the default sort routines.
In this case you should be able to use something like:
[y[1] for y in sorted([(myDict[x][2], x) for x in myDict.keys()])]
... that's a list comprehension doing the undecorate from the sorted list of tuples which is being returned by the inner list comprehension. The inner comprehension is creating a set of tuples, your desired sorting key (the 3rd element of the list) and the dictionary's key corresponding to the sorting key. myDict.keys() is, of course, a method of Python dictionaries which returns a list of all valid keys in whatever order the underlying implementation chooses --- presumably a simple iteration over the hashes.
A more verbose way of doing this might be easier to read:
temp = list()
for k, v in myDict.items():
temp.append((v[2],))
temp.sort()
results = list()
for i in temp:
results.append(i[1])
Usually you should built up such code iteratively, in the interpreter using small data samples. Build the "decorate" expression or function. Then wrap that in a call to sorted(). Then build the undecorate expression (which is usually as simple as what I've shown here).
Now you can do this; returns a dictionary itself. Boolean at the end is to determine if the order is ascending or descending.
sorted_dict = dict(sorted(myDict.items(), key=lambda item: item[1][2], reverse=True))

Categories

Resources