Are sorted keys guaranteed by a Python dictionary? - python

That iterating over a dict could yield sorted keys was surprising. It would be considerably useful too, if this is a guaranteed behaviour.
example code
fruits = {3: "banana",
4: "grapes",
1: "apple",
2: "cherry"}
# Looping over the dict itelf
for each in fruits:
print each, fruits[each]
output
1 apple
2 cherry
3 banana
4 grapes
# Looping over the generator produces the same result too
for each in iter(fruits):
print each, fruits[each]
Note: I would like to point out that I don't want implement an ordered dict. I just wanted to verify if the code written above is a normal, recurring behavior in python (version 2.7 above)

You can subclass the dict and create your own SortedDict class, like this
class SortedDict(dict):
def __iter__(self):
return iter(sorted(super(SortedDict, self).__iter__()))
def items(self):
return iter((k, self[k]) for k in self)
fruits = SortedDict({3: "banana",
4: "grapes",
1: "apple",
2: "cherry"})
for each in fruits:
print each, fruits[each]
Complete working implementation is here

From the docs:
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.

Iteration over a dict is not guaranteed to produce any particular order. In particular, it is not guaranteed to be sorted, it is not guaranteed to be in insertion order, it may be different between equal dicts, and it may be different from one execution of the interpreter to another. Here's an example:
>>> dict.fromkeys([-1, -2])
{-2: None, -1: None}
>>> dict.fromkeys([-2, -1])
{-1: None, -2: None}
Two equal dicts, two different orders. Neither dict is in the order the keys were inserted in, and the second dict's keys aren't in sorted order.
If you want to iterate over the keys in sorted order, use
for key in sorted(d)
If you want to iterate over the keys in the order they were inserted in, use a collections.OrderedDict.

Besides OrderedDict, you can just use the built-in sorted function to iterate a dict:
fruits = {3: "banana",
4: "grapes",
1: "apple",
2: "cherry"}
for each in sorted(fruits.items(), key=lambda i:i[0]):
print each[0], each[1]
BTW, sorted() returns a two element tuple list, not a dict.

As the docs state, no, keys are not sorted in a Python dict. But many people have found that behavior useful and there exist many implementations of sorted dicts on PyPI. The SortedDict data type does exactly what you observed: efficiently maintains its keys in sorted order.
One such implementation is the sortedcontainers module which provides sorted list, sorted dict, and sorted set data types. It's implemented in pure-Python but is fast-as-C implementations. Unit tests provide 100% coverage and it's passed hours of stress testing.
Perhaps most importantly, sortedcontainers maintains a performance comparison of several popular implementations along with a description of their tradeoffs.

Related

Randomize dictionary sorting

I have been thinking this through but I did not come to any conclusion (not that great with Python yet).
My dictionary looks like this:
{1: [dog, animal], 2: [square, shape], 3: [red, color]}
I am printing out the values but the dictionary is sorted by numbers, which is fine but I want to randomize it so I print out something like this:
3
red
color
1
dog
animal
2
square
shape
I know that list would be more ideal for this situation but this data is from existing structure that I cannot change. Maybe re-numbering the keys would do the trick?
Dictionaries are already listed in arbitrary order, they do not have a fixed order. See Why is the order in dictionaries and sets arbitrary? Any sense of order is a coincidence and depends on the insertion and deletion history of the dictionary.
That said, it's easy enough to further ensure a shuffled list with random.shuffle():
import random
items = yourdict.items()
random.shuffle(items)
for key, value in items:
print key
print '\n'.join(value)
You can randomize the keys:
import random
....
keys = dictionary.keys()
random.shuffle(keys)
for key in keys:
print key, dictionary[key]

python interpreter returning blank dictionary after calling imported function

I'm trying to learn python (with a VBA background).
I've imported the following function into my interpreter:
def shuffle(dict_in_question): #takes a dictionary as an argument and shuffles it
shuff_dict = {}
n = len(dict_in_question.keys())
for i in range(0, n):
shuff_dict[i] = pick_item(dict_in_question)
return shuff_dict
following is a print of my interpreter;
>>> stuff = {"a":"Dave", "b":"Ben", "c":"Harry"}
>>> stuff
{'a': 'Dave', 'c': 'Harry', 'b': 'Ben'}
>>> decky11.shuffle(stuff)
{0: 'Harry', 1: 'Dave', 2: 'Ben'}
>>> stuff
{}
>>>
It looks like the dictionary gets shuffled, but after that, the dictionary is empty. Why? Or, am I using it wrong?
You need to assign it back to stuff too, as you're returning a new dictionary.
>>> stuff = decky11.shuffle(stuff)
Dogbert's answer solves your immediate problem, but keep in mind that dictionaries don't have an order! There's no such thing as "the first element of my_dict." (Using .keys() or .values() generates a list, which does have an order, but the dictionary itself doesn't.) So, it's not really meaningful to talk about "shuffling" a dictionary.
All you've actually done here is remapped the keys from letters a, b, c, to integers 0, 1, 2. These keys have different hash values than the keys you started with, so they print in a different order. But you haven't changed the order of the dictionary, because the dictionary didn't have an order to begin with.
Depending on what you're ultimately using this for (are you iterating over keys?), you can do something more direct:
shufflekeys = random.shuffle(stuff.keys())
for key in shufflekeys:
# do thing that requires order
As a side note, dictionaries (aka hash tables) are a really clever, hyper-useful data structure, which I'd recommend learning deeply if you're not already familiar. A good hash function (and non-pathological data) will give you O(1) (i.e., constant) lookup time - so you can check if a key is in a dictionary of a million items as fast as you can in a dictionary of ten items! The lack of order is a critical feature of a dictionary that enables this speed.

update method for dictionaries-Python

I have written a code which tries to sort a dictionary using the values rather than keys
""" This module sorts a dictionary based on the values of the keys"""
adict={1:1,2:2,5:1,10:2,44:3,67:2} #adict is an input dictionary
items=adict.items()## converts the dictionary into a list of tuples
##print items
list_value_key=[ [d[1],d[0]] for d in items] """Interchanges the position of the
key and the values"""
list_value_key.sort()
print list_value_key
key_list=[ list_value_key[i][1] for i in range(0,len(list_value_key))]
print key_list ## list of keys sorted on the basis of values
sorted_adict={}
*for key in key_list:
sorted_adict.update({key:adict[key]})
print key,adict[key]
print sorted_adict*
So when I print key_list i get the expected answer, but for the last part of the code where i try to update the dictionary, the order is not what it should be. Below are the results obtained. I am not sure why the "update" method is not working. Any help or pointers is appreciated
result:
sorted_adict={1: 1, 2: 2, 67: 2, 5: 1, 10: 2, 44: 3}
Python dictionaries, no matter how you insert into them, are unordered. This is the nature of hash tables, in general.
Instead, perhaps you should keep a list of keys in the order their values or sorted, something like: [ 5, 1, 44, ...]
This way, you can access your dictionary in sorted order at a later time.
Don't sort like that.
import operator
adict={1:1,2:2,5:1,10:2,44:3,67:2}
sorted_adict = sorted(adict.iteritems(), key=operator.itemgetter(1))
If you need a dictionary that retains its order, there's a class called OrderedDict in the collections module. You can use the recipes on that page to sort a dictionary and create a new OrderedDict that retains the sort order. The OrderedDict class is available in Python 2.7 or 3.1.
To sort your dictionnary, you could also also use :
adict={1:1,2:2,5:1,10:2,44:3,67:2}
k = adict.keys()
k.sort(cmp=lambda k1,k2: cmp(adict[k1],adict[k2]))
And by the way, it's useless to reuse a dictionnary after that because there are no order in dict (they are just mapping types - you can have keys of different types that are not "comparable").
One problem is that ordinary dictionaries can't be sorted because of the way they're implemented internally. Python 2.7 and 3.1 had a new class namedOrderedDictadded to theircollectionsmodule as #kindall mentioned in his answer. While they can't be sorted exactly either, they do retain or remember the order in which keys and associated values were added to them, regardless of how it was done (including via theupdate() method). This means that you can achieve what you want by adding everything from the input dictionary to anOrderedDictoutput dictionary in the desired order.
To do that, the code you had was on the right track in the sense of creating what you called thelist_value_keylist and sorting it. There's a slightly simpler and faster way to create the initial unsorted version of that list than what you were doing by using the built-inzip()function. Below is code illustrating how to do that:
from collections import OrderedDict
adict = {1:1, 2:2, 5:1, 10:2, 44:3, 67:2} # input dictionary
# zip together and sort pairs by first item (value)
value_keys_list = sorted(zip(adict.values(), adict.keys()))
sorted_adict = OrderedDict() # value sorted output dictionary
for pair in value_keys_list:
sorted_adict[pair[1]] = pair[0]
print sorted_adict
# OrderedDict([(1, 1), (5, 1), (2, 2), (10, 2), (67, 2), (44, 3)])
The above can be rewritten as a fairly elegant one-liner:
sorted_adict = OrderedDict((pair[1], pair[0])
for pair in sorted(zip(adict.values(), adict.keys())))

In Python, when to use a Dictionary, List or Set?

When should I use a dictionary, list or set?
Are there scenarios that are more suited for each data type?
A list keeps order, dict and set don't: when you care about order, therefore, you must use list (if your choice of containers is limited to these three, of course ;-) ).
dict associates each key with a value, while list and set just contain values: very different use cases, obviously.
set requires items to be hashable, list doesn't: if you have non-hashable items, therefore, you cannot use set and must instead use list.
set forbids duplicates, list does not: also a crucial distinction. (A "multiset", which maps duplicates into a different count for items present more than once, can be found in collections.Counter -- you could build one as a dict, if for some weird reason you couldn't import collections, or, in pre-2.7 Python as a collections.defaultdict(int), using the items as keys and the associated value as the count).
Checking for membership of a value in a set (or dict, for keys) is blazingly fast (taking about a constant, short time), while in a list it takes time proportional to the list's length in the average and worst cases. So, if you have hashable items, don't care either way about order or duplicates, and want speedy membership checking, set is better than list.
Do you just need an ordered sequence of items? Go for a list.
Do you just need to know whether or not you've already got a particular value, but without ordering (and you don't need to store duplicates)? Use a set.
Do you need to associate values with keys, so you can look them up efficiently (by key) later on? Use a dictionary.
When you want an unordered collection of unique elements, use a set. (For example, when you want the set of all the words used in a document).
When you want to collect an immutable ordered list of elements, use a tuple. (For example, when you want a (name, phone_number) pair that you wish to use as an element in a set, you would need a tuple rather than a list since sets require elements be immutable).
When you want to collect a mutable ordered list of elements, use a list. (For example, when you want to append new phone numbers to a list: [number1, number2, ...]).
When you want a mapping from keys to values, use a dict. (For example, when you want a telephone book which maps names to phone numbers: {'John Smith' : '555-1212'}). Note the keys in a dict are unordered. (If you iterate through a dict (telephone book), the keys (names) may show up in any order).
Use a dictionary when you have a set of unique keys that map to values.
Use a list if you have an ordered collection of items.
Use a set to store an unordered set of items.
In short, use:
list - if you require an ordered sequence of items.
dict - if you require to relate values with keys
set - if you require to keep unique elements.
Detailed Explanation
List
A list is a mutable sequence, typically used to store collections of homogeneous items.
A list implements all of the common sequence operations:
x in l and x not in l
l[i], l[i:j], l[i:j:k]
len(l), min(l), max(l)
l.count(x)
l.index(x[, i[, j]]) - index of the 1st occurrence of x in l (at or after i and before j indeces)
A list also implements all of the mutable sequence operations:
l[i] = x - item i of l is replaced by x
l[i:j] = t - slice of l from i to j is replaced by the contents of the iterable t
del l[i:j] - same as l[i:j] = []
l[i:j:k] = t - the elements of l[i:j:k] are replaced by those of t
del l[i:j:k] - removes the elements of s[i:j:k] from the list
l.append(x) - appends x to the end of the sequence
l.clear() - removes all items from l (same as del l[:])
l.copy() - creates a shallow copy of l (same as l[:])
l.extend(t) or l += t - extends l with the contents of t
l *= n - updates l with its contents repeated n times
l.insert(i, x) - inserts x into l at the index given by i
l.pop([i]) - retrieves the item at i and also removes it from l
l.remove(x) - remove the first item from l where l[i] is equal to x
l.reverse() - reverses the items of l in place
A list could be used as stack by taking advantage of the methods append and pop.
Dictionary
A dictionary maps hashable values to arbitrary objects. A dictionary is a mutable object. The main operations on a dictionary are storing a value with some key and extracting the value given the key.
In a dictionary, you cannot use as keys values that are not hashable, that is, values containing lists, dictionaries or other mutable types.
Set
A set is an unordered collection of distinct hashable objects. A set is commonly used to include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference.
For C++ I was always having this flow chart in mind: In which scenario do I use a particular STL container?, so I was curious if something similar is available for Python3 as well, but I had no luck.
What you need to keep in mind for Python is: There is no single Python standard as for C++. Hence there might be huge differences for different Python interpreters (e.g. CPython, PyPy). The following flow chart is for CPython.
Additionally I found no good way to incorporate the following data structures into the diagram: bytes, byte arrays, tuples, named_tuples, ChainMap, Counter, and arrays.
OrderedDict and deque are available via collections module.
heapq is available from the heapq module
LifoQueue, Queue, and PriorityQueue are available via the queue module which is designed for concurrent (threads) access. (There is also a multiprocessing.Queue available but I don't know the differences to queue.Queue but would assume that it should be used when concurrent access from processes is needed.)
dict, set, frozen_set, and list are builtin of course
For anyone I would be grateful if you could improve this answer and provide a better diagram in every aspect. Feel free and welcome.
PS: the diagram has been made with yed. The graphml file is here
Although this doesn't cover sets, it is a good explanation of dicts and lists:
Lists are what they seem - a list of values. Each one of them is
numbered, starting from zero - the first one is numbered zero, the
second 1, the third 2, etc. You can remove values from the list, and
add new values to the end. Example: Your many cats' names.
Dictionaries are similar to what their name suggests - a dictionary.
In a dictionary, you have an 'index' of words, and for each of them a
definition. In python, the word is called a 'key', and the definition
a 'value'. The values in a dictionary aren't numbered - tare similar
to what their name suggests - a dictionary. In a dictionary, you have
an 'index' of words, and for each of them a definition. The values in
a dictionary aren't numbered - they aren't in any specific order,
either - the key does the same thing. You can add, remove, and modify
the values in dictionaries. Example: telephone book.
http://www.sthurlow.com/python/lesson06/
In combination with lists, dicts and sets, there are also another interesting python objects, OrderedDicts.
Ordered dictionaries are just like regular dictionaries but they remember the order that items were inserted. When iterating over an ordered dictionary, the items are returned in the order their keys were first added.
OrderedDicts could be useful when you need to preserve the order of the keys, for example working with documents: It's common to need the vector representation of all terms in a document. So using OrderedDicts you can efficiently verify if a term has been read before, add terms, extract terms, and after all the manipulations you can extract the ordered vector representation of them.
May be off topic in terms of the question OP asked-
List: A unhashsable collection of ordered, mutable objects.
Tuple: A hashable collection of ordered, immutable objects, like
list.
Set: An unhashable collection of unordered, mutable and distinct
objects.
Frozenset: A hashable collection of unordered, immutable and
distinct objects.
Dictionary : A unhashable,unordered collection of mutable objects
that maps hashable values to arbitrary values.
To compare them visually, at a glance, see the image-
Lists are what they seem - a list of values. Each one of them is numbered, starting from zero - the first one is numbered zero, the second 1, the third 2, etc. You can remove values from the list, and add new values to the end. Example: Your many cats' names.
Tuples are just like lists, but you can't change their values. The values that you give it first up, are the values that you are stuck with for the rest of the program. Again, each value is numbered starting from zero, for easy reference. Example: the names of the months of the year.
Dictionaries are similar to what their name suggests - a dictionary. In a dictionary, you have an 'index' of words, and for each of them a definition. In python, the word is called a 'key', and the definition a 'value'. The values in a dictionary aren't numbered - tare similar to what their name suggests - a dictionary. In a dictionary, you have an 'index' of words, and for each of them a definition. In python, the word is called a 'key', and the definition a 'value'. The values in a dictionary aren't numbered - they aren't in any specific order, either - the key does the same thing. You can add, remove, and modify the values in dictionaries. Example: telephone book.
When use them, I make an exhaustive cheatsheet of their methods for your reference:
class ContainerMethods:
def __init__(self):
self.list_methods_11 = {
'Add':{'append','extend','insert'},
'Subtract':{'pop','remove'},
'Sort':{'reverse', 'sort'},
'Search':{'count', 'index'},
'Entire':{'clear','copy'},
}
self.tuple_methods_2 = {'Search':'count','index'}
self.dict_methods_11 = {
'Views':{'keys', 'values', 'items'},
'Add':{'update'},
'Subtract':{'pop', 'popitem',},
'Extract':{'get','setdefault',},
'Entire':{ 'clear', 'copy','fromkeys'},
}
self.set_methods_17 ={
'Add':{['add', 'update'],['difference_update','symmetric_difference_update','intersection_update']},
'Subtract':{'pop', 'remove','discard'},
'Relation':{'isdisjoint', 'issubset', 'issuperset'},
'operation':{'union' 'intersection','difference', 'symmetric_difference'}
'Entire':{'clear', 'copy'}}
Dictionary: A python dictionary is used like a hash table with key as index and object as value.
List: A list is used for holding objects in an array indexed by position of that object in the array.
Set: A set is a collection with functions that can tell if an object is present or not present in the set.
Dictionary: When you want to look up something using something else than indexes. Example:
dictionary_of_transport = {
"cars": 8,
"boats": 2,
"planes": 0
}
print("I have the following amount of planes:")
print(dictionary_of_transport["planes"])
#Output: 0
List and sets: When you want to add and remove values.
Lists: To look up values using indexes
Sets: To have values stored, but you cannot access them using anything.

How to print unsorted dictionary in python?

I have this dict in python;
d={}
d['b']='beta'
d['g']='gamma'
d['a']='alpha'
when i print the dict;
for k,v in d.items():
print k
i get this;
a
b
g
it seems like python sorts the dict automatically! how can i get the original unsorted list?
Gath
Dicts don't work like that:
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.
You could use a list with 2-tuples instead:
d = [('b', 'beta'), ('g', 'gamma'), ('a', 'alpha')]
A similar but better solution is outlined in Wayne's answer.
As has been mentioned, dicts don't order or unorder the items you put in. It's "magic" as to how it's ordered when you retrieve it. If you want to keep an order -sorted or not- you need to also bind a list or tuple.
This will give you the same dict result with a list that retains order:
greek = ['beta', 'gamma', 'alpha']
d = {}
for x in greek:
d[x[0]] = x
Simply change [] to () if you have no need to change the original list/order.
Don't use a dictionary. Or use the Python 2.7/3.1 OrderedDict type.
There is no order in dictionaries to speak of, there is no original unsorted list.
No, python does not sort dict, it would be too expensive. The order of items() is arbitrary. From python docs:
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.

Categories