I'm trying to make a dictionary in Python that I can sort through but it seems to change order when I add new things. Is there a way around this?
A standard Dictionary does not impose an ordering, it's simply a lookup.
You want an Ordered Dictionary or Ordered Dictionary.
Python dicts are built as hash tables -- great performance, but ordering is essentially arbitrary and unpredictable. If your need for predictably-ordered walks are occasional, and based on keys or values, the sorted built-in is very handy:
# print all entries in sorted key order
for k in sorted(d): print k, d[k]
# print all entries in reverse-sorted value order
for k in sorted(d, key=d.get, reverse=True): print k, d[k]
# given all keys are strings, print in case-insensitive sorted order
for k in sorted(d, key=str.lower): print k, d[k]
and so forth. If you needs are different (e.g., keep track of the respective times at which keys are inserted, or their values altered, and so forth), the "ordered dictionaries" suggested in other answers will serve you better (but never with the awesome raw performance of a true dict!-).
Related
How to sort a list of 1 billion elements in python
Please elaborate
Assuming we have unlimited space.
Thanks for the answers, but, this question is asked in the perspective of optimizing algorithm to sort, not to work on python. This question is asked in an interview, in the context of, having large number of elements, may be integers or strings, this probably wont be used in real world as we have techniques like pagination.
Dictionaries are unordered. They are hash tables and you are not guaranteed the order of keys in a hash table.
If you require the keys to be ordered, try the ordered dict class in collections.
If you need to sort the keys you could place them in a list, and sort the list.
my_dict = {key: value for key, value in zip(keys, values)} # Example dict
keys = [i for i in my_dict]
keys.sort()
A dictionary on its own does not store a key order. For this, you will have to use the OrderedDict which stores the order of insertion.
If you just need to iterate through the sorted keys, you can use sorted:
for key in sorted(my_dict):
# output is already sorted by dictionary key
print key, my_dict[key]
if you need to specify a special key or method, you could pass this as information to sorted. The following example sorts by value:
for key, value in sorted(my_dict.items(), key=lambda x: x[1]):
# output is sorted by value
print key, value
Sort orders can be reversed by using reversed:
for key in reversed(sorted(my_dict)):
# output is already sorted descending by dictionary key
print key, my_dict[key]
Finally, this code snippet would fill an OrderedDict with sorted key/value pairs:
from collections import OrderedDict
my_ordered_dict = OrderedDict(sorted(my_dict.items(), key=lambda t: t[0]))
Since you updated your question from dictionary to list
Sorting lists is even easier, just use sorted (again, provide a small method, if you have a different sorting key):
sorted_list = sorted(unsorted_list)
I have a dictionary where the keys are an arbitrary name and the values are an mtime of a file. Example:
{'server_1': 1506286408.854673, 'server_2': 1506286219.1254442, 'server_3':1506472359.154043}
I wish to iterate over comparing two of the values from the dictionary finding the largest of the two, and returning the key of said large value and continuing to do this until there is only a single key:val pair left.
I know there is a way of "ordering" dictionaries by value with some tricks provided by outside libraries like operator and defaultdict. However, I was curious if there was an easier way to accomplish this goal and avoid trying to sort a naturally unordered structure.
So the end result I would be looking for is the first iteration to return server_3, then server_1 and then stop there.
It looks like you want to sort dictionary based on values but ignore the last one.
def keys_sorted_by_values(d):
return [ k for k, v in sorted(d.items(), key=lambda item: item[1], reverse=True) ][:-1]
server_to_mtime = {'server_1': 1506286408.854673, 'server_2': 1506286219.1254442, 'server_3':1506472359.154043}
for server in keys_sorted_by_values(server_to_mtime):
print(server)
Output
server_3
server_1
P/S: Duplicates questions raised so far are concerning on prefixes (thanks for that anyway)
This question is on suffixes.
With dictionary
dic={"abcd":2, "bbcd":2, "abgg":2}
Is it possible to search the dictionary using suffix of the string, i.e., if given "bcd", it will return me two entries
{"abcd":2, "bbcd":2}
One possible way:
dic1={}
for k, v in dic.items():
if(k.endswith("bcd")):
dic1[k]=v
Is it possible to do it more efficiently?
for a small problems set you can do it with a simple list comprehension:
suffixed = [v for k, v in dic.items() if k.endswith("bcd")]
however that means doing a substring check on every item in the dictionary every time you query. If that's slow on big data sets you can make a second dictionary of the original keys as an acceleration. You'd have to do a one time pre-pass:
suffixes = dict ( [ (k[-3:], []) for k in dic1] )
for k in dic1:
suffixes[k[-3:]].append(dic1[k])
That would give you all the results for each suffix. You could store the keys instead of the values the same way and then chain to a lookup.
In any event, the hashed lookups for dictionary keys are very cheap, so it's best to cache your data in a dictionary with the keys you want (ie, suffixes) rather than looping over every key doing strings.
I have a dictionary such as below.
d = {
'0:0:7': '19734',
'0:0:0': '4278',
'0:0:21': '19959',
'0:0:14': '9445',
'0:0:28': '14205',
'0:0:35': '3254'
}
Now I want to sort it by keys with time priority.
Dictionaries are not sorted, if you want to print it out or iterate through it in sorted order, you should convert it to a list first:
e.g.:
sorted_dict = sorted(d.items(), key=parseTime)
#or
for t in sorted(d, key=parseTime):
pass
def parseTime(s):
return tuple(int(x) for x in s.split(':'))
Note that this will mean you can not use the d['0:0:7'] syntax for sorted_dict though.
Passing a 'key' argument to sorted tells python how to compare the items in your list, standard string comparison will not work to sort by time.
Dictionaries in python have no guarantees on order. There is collections.OrderedDict, which retains insertion order, but if you want to work through the keys of a standard dictionary in order you can just do:
for k in sorted(d):
In your case, the problem is that your time strings won't sort correctly. You need to include the additional zeroes needed to make them do so, e.g. "00:00:07", or interpret them as actual time objects, which will sort correctly. This function may be useful:
def padded(s, c=":"):
return c.join("{0:02d}".format(int(i)) for i in s.split(c))
You can use this as a key for sorted if you really want to retain the current format in your output:
for k in sorted(d, key=padded):
Have a look at the collections.OrderedDict module
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.