Python Dictionay sort [duplicate] - python

This question already has answers here:
How do I sort a dictionary by value?
(34 answers)
Closed 10 years ago.
I have a dictionary like
>>> x = {'a':2, 'c': 1, 'b':3}
There is no method available in dictionary to sort the dictionary by value. I sorted it using
>>> sorted_x = sorted(x.iteritems(), key=operator.itemgetter(1))
>>> sorted_x
[('c', 1), ('a', 2), ('b', 3)]
but now when I convert to sorted_x to dictionary again by using loop. like
>>> new_dict = {}
>>> for i in sorted_x:
new_dict[i[0]] = i[1]
>>> new_dict
{'a': 2, 'c': 1, 'b': 3}
The new_dict again remains unsorted. Why the python dictionary cannot be sorted by key? can anyone shed light on it.

Dictionaries are unsorted. They're just mappings between keys and values.
If you want a sorted dictionary, use collections.OrderedDict:
>>> import collections
>>> d = collections.OrderedDict(sorted_x)
>>> d
OrderedDict([('c', 1), ('a', 2), ('b', 3)])
>>> d['c']
1

Dictionaries in python are hash maps. The keys are hashed in order to keep a fast access to the elements.
This means that internally the elements must be ordered depending on the hash they generate, not depending on the order you want to give.

Related

merge two dictionaries in python 2.7

how to merge two dictionaries in python 2.7 without changing the order of keys in it. as I have to make a CSV file in the required order. I just want to add B dictionary after A dictionary values.
def Merge(A,B):
m=A.copy()
m.update(B)
return m
I am using this method. I also try with +. but the same result. ** is not working in python 2.7
Dictionaries are unordered containers. So, what you say is not correct. That is, if you simply have two dictionaries, then you have no order.
BUT! You have can order the keys of a dictionary, using the OrderedDict container.
You can consider something like:
>>> from collections import OrderedDict
>>> a = OrderedDict({'a': 1, 'b': 2})
>>> b = OrderedDict({'c': 3, 'd': 4})
>>> c = OrderedDict()
>>>for d in [a, b]:
... for k, v in d.items():
... c.update({k :v})
>>> print(c)
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
# Or
>>> d = OrderedDict()
>>> d.update(a.copy())
>>> d.update(b.copy())
>>> print(d)
OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
Or, if you want a function:
from collections import OrderedDict
def merge(a, b):
c = OrderedDict()
c.update(a.copy())
c.update(b.copy())
return c
You can read more about OrderedDict here.
Dictionaries are unordered in Python 2. If you need to preserve the order of keys, you'll have to use something else, like a list of pairs, or an OrderedDict. Here's one approach.
from collections import OrderedDict
def merge(a, b):
return OrderedDict((k, v) for d in [a, b] for k, v in d.items())
Dictionaries is considered as an unordered collection of values mapped to certain keys. First, make an ordered dictionary by using OrderedDict from the collections library. Then using the method update() you can create the new dictionary. Here's an example.
# A Python program to demonstrate working of OrderedDict
from collections import OrderedDict
#Form OrderedDicts
dict1 = OrderedDict({"a": 1, "b": 2})
dict2 = OrderedDict({"c": 3, "d": 4})
print "These are two ordered dictionaries:\n"
print dict1 , dict2
#Using update method in python
def Merge(dict1, dict2):
return(dict1.update(dict2))
#Make a duplicate of the first dictionary
dict3 = dict1
#Call function
Merge(dict3, dict2)
print "Combined dictionary:", dict3
If you are just going to make a csv you can create a list of items from both ensuring that the items from one are after the items of the other. Then use the list of tuples to make the csv.
a = {1:1,2:2}
b = {3:3,4:4}
combined = []
combined.extend(a.items())
combined.extend(b.items())
In [8]: combined
Out[8]: [(1, 1), (2, 2), (3, 3), (4, 4)]

Build a new dictionary from the keys of one dictionary and the values of another dictionary

I have two dictionaries:
dict_1 = ({'a':1, 'b':2,'c':3})
dict_2 = ({'x':4,'y':5,'z':6})
I want to take the keys from dict_1 and values from dict_2
and make a new dict_3
dict_3 = ({'a':4,'b':5,'c':6})
What you are trying to do is impossible to do in any predictable way using regular dictionaries. As #PadraicCunningham and others have already pointed out in the comments, the order of dictionaries is arbitrary.
If you still want to get your result, you must use ordered dictionaries from the start.
>>> from collections import OrderedDict
>>> d1 = OrderedDict((('a',1), ('b',2), ('c', 3)))
>>> d2 = OrderedDict((('x',4), ('y',5), ('z', 6)))
>>> d3 = OrderedDict(zip(d1.keys(), d2.values()))
>>> d3
OrderedDict([('a', 4), ('b', 5), ('c', 6)])
You can achieve this using zip and converting the resulting list to a dict:
dict(zip(dict_1.keys(), dict_2.values()))
But since the dictionaries are unordered, it won't be identical to your expected result:
{'a': 5, 'c': 4, 'b': 6}

Python - sorting/querying a dictionary? [duplicate]

This question already has answers here:
Get the second largest number in a list in linear time
(31 answers)
Closed 8 years ago.
I'm relatively new to Python (2.7 import future) so please forgive me if this is a stupid question.
I've got a dictionary of values[key]. I'm trying to get the second highest value from the list, but write readable code. I could do it by mapping to sortable types, but it's confusing as hell, and then I would have to juggle the key. Any suggestions for how to do it cleanly would be much appreciated.
2nd highest value in a dictionary:
from operator import itemgetter
# Note that this now returns a k, v pair, not just the value.
sorted(mydict.items(), key = itemgetter(1))[1]
Or more specifically, the 2nd value in the sorted representation of values. You may need to reverse sort order to get the value you actually want.
If you also want the key associated with that value, I would do something like:
# Initialize dict
In [1]: from random import shuffle
In [2]: keys = list('abcde')
In [3]: shuffle(keys)
In [4]: d = dict(zip(keys, range(1, 6)))
In [5]: d
Out[5]: {'a': 4, 'b': 1, 'c': 5, 'd': 3, 'e': 2}
# Retrieve second highest value with key
In [6]: sorted_pairs = sorted(d.iteritems(), key=lambda p: p[1], reverse=True)
In [7]: sorted_pairs
Out[7]: [('c', 5), ('a', 4), ('d', 3), ('e', 2), ('b', 1)]
In [8]: sorted_pairs[1]
Out[8]: ('a', 4)
The key=lambda p: p[1] tells sorted to sort the (key, value) pairs by the value, and reverse tells sorted to place the largest values first in the resulting list.
This should do the trick:
maximum, max_key = None, None
second, second_key = None, None
for key, value in dictionary.iteritems():
if maximum < value:
second = maximum
second_key = max_key
maximum = value
maxi_key = second_key

Python: Iterate alphabetically over OrderedDict

In a script I have an OrderedDict groups that gets fed key/value pairs alphabetically.
In another part of the script, I'm checking against files that have the same same as key like so:
for (key, value) in groups.items():
file = open(key, 'r')
# do stuff
Stuff happens just fine, part of which is printing a status line for each file, but how can I get Python to iterate through groups alphabetically, or at least numerically as they are ordered (since they are being entered in alphabetical order anyways)?
The whole point of an OrderedDict is that you can iterate through it normally in the order that keys were entered:
>>> from collections import OrderedDict
>>> d = OrderedDict()
>>> d[1] = 2
>>> d[0] = 3
>>> d[9] = 2
>>> for k, v in d.items():
print(k, v)
(1, 2)
(0, 3)
(9, 2)
Just make sure you don't feed OrderedDict(...) a dictionary to initialize it or it starts off unordered.
If all you want to do is iterate through a dictionary in order of the keys, you can use a regular dictionary and sorted():
>>> d = dict(s=5,g=4,a=6,j=10)
>>> d
{'g': 4, 's': 5, 'j': 10, 'a': 6}
>>> for k in sorted(d):
print(k, ':', d[k])
a : 6
g : 4
j : 10
s : 5
>>>
(pardon the python3 print())
If you really want to stick with the ordered dict, then read the documentation which shows an example of reordering an OrderedDict:
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
If you really entered them into an OrderedDict alphabetically in the first place, then I'm not sure why you're having trouble.

Return first N key:value pairs from dict

Consider the following dictionary, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
I want to return the first N key:value pairs from d (N <= 4 in this case). What is the most efficient method of doing this?
There's no such thing a the "first n" keys because a dict doesn't remember which keys were inserted first.
You can get any n key-value pairs though:
n_items = take(n, d.items())
This uses the implementation of take from the itertools recipes:
from itertools import islice
def take(n, iterable):
"""Return the first n items of the iterable as a list."""
return list(islice(iterable, n))
See it working online: ideone
For Python < 3.6
n_items = take(n, d.iteritems())
A very efficient way to retrieve anything is to combine list or dictionary comprehensions with slicing. If you don't need to order the items (you just want n random pairs), you can use a dictionary comprehension like this:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
Generally a comprehension like this is always faster to run than the equivalent "for x in y" loop. Also, by using .keys() to make a list of the dictionary keys and slicing that list you avoid 'touching' any unnecessary keys when you build the new dictionary.
If you don't need the keys (only the values) you can use a list comprehension:
first2vals = [v for v in mydict.values()[:2]]
If you need the values sorted based on their keys, it's not much more trouble:
first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
or if you need the keys as well:
first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
To get the top N elements from your python dictionary one can use the following line of code:
list(dictionaryName.items())[:N]
In your case you can change it to:
list(d.items())[:4]
Python's dicts are not ordered, so it's meaningless to ask for the "first N" keys.
The collections.OrderedDict class is available if that's what you need. You could efficiently get its first four elements as
import itertools
import collections
d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)
for key, value in x:
print key, value
itertools.islice allows you to lazily take a slice of elements from any iterator. If you want the result to be reusable you'd need to convert it to a list or something, like so:
x = list(itertools.islice(d.items(), 0, 4))
foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
print(next(iterator))
Basically, turn the view (dict_items) into an iterator, and then iterate it with next().
in py3, this will do the trick
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
You can get dictionary items by calling .items() on the dictionary. then convert that to a list and from there get first N items as you would on any list.
below code prints first 3 items of the dictionary object
e.g.
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
first_three_items = list(d.items())[:3]
print(first_three_items)
Outputs:
[('a', 3), ('b', 2), ('c', 3)]
For Python 3.8 the correct answer should be:
import more_itertools
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
first_n = more_itertools.take(3, d.items())
print(len(first_n))
print(first_n)
Whose output is:
3
[('a', 3), ('b', 2), ('c', 3)]
After pip install more-itertools of course.
Did not see it on here. Will not be ordered but the simplest syntactically if you need to just take some elements from a dictionary.
n = 2
{key:value for key,value in d.items()[0:n]}
Were d is your dictionary and n is the printing number:
for idx, (k, v) in enumerate(d.items()):
if idx == n: break
print(k, v)
Casting your dictionary to a list can be slow.
Your dictionary may be too large and you don't need to cast all of it just for printing a few of the first.
See PEP 0265 on sorting dictionaries. Then use the aforementioned iterable code.
If you need more efficiency in the sorted key-value pairs. Use a different data structure. That is, one that maintains sorted order and the key-value associations.
E.g.
import bisect
kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))
print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
just add an answer using zip,
{k: d[k] for k, _ in zip(d, range(n))}
This will work for python 3.8+:
d_new = {k:v for i, (k, v) in enumerate(d.items()) if i < n}
This depends on what is 'most efficient' in your case.
If you just want a semi-random sample of a huge dictionary foo, use foo.iteritems() and take as many values from it as you need, it's a lazy operation that avoids creation of an explicit list of keys or items.
If you need to sort keys first, there's no way around using something like keys = foo.keys(); keys.sort() or sorted(foo.iterkeys()), you'll have to build an explicit list of keys. Then slice or iterate through first N keys.
BTW why do you care about the 'efficient' way? Did you profile your program? If you did not, use the obvious and easy to understand way first. Chances are it will do pretty well without becoming a bottleneck.
For Python 3 and above,To select first n Pairs
n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}
This might not be very elegant, but works for me:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
x= 0
for key, val in d.items():
if x == 2:
break
else:
x += 1
# Do something with the first two key-value pairs
You can approach this a number of ways. If order is important you can do this:
for key in sorted(d.keys()):
item = d.pop(key)
If order isn't a concern you can do this:
for i in range(4):
item = d.popitem()
Dictionary maintains no order , so before picking top N key value pairs lets make it sorted.
import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values
Now we can do the retrieval of top 'N' elements:, using the method structure like this:
def return_top(elements,dictionary_element):
'''Takes the dictionary and the 'N' elements needed in return
'''
topers={}
for h,i in enumerate(dictionary_element):
if h<elements:
topers.update({i:dictionary_element[i]})
return topers
to get the top 2 elements then simply use this structure:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)
consider a dict
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice will do the trick :)
hope it helps !
I have tried a few of the answers above and note that some of them are version dependent and do not work in version 3.7.
I also note that since 3.6 all dictionaries are ordered by the sequence in which items are inserted.
Despite dictionaries being ordered since 3.6 some of the statements you expect to work with ordered structures don't seem to work.
The answer to the OP question that worked best for me.
itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
def GetNFirstItems(self):
self.dict = {f'Item{i + 1}': round(uniform(20.40, 50.50), 2) for i in range(10)}#Example Dict
self.get_items = int(input())
for self.index,self.item in zip(range(len(self.dict)),self.dict.items()):
if self.index==self.get_items:
break
else:
print(self.item,",",end="")
Unusual approach, as it gives out intense O(N) time complexity.
I like this one because no new list needs to be created, its a one liner which does exactly what you want and it works with python >= 3.8 (where dictionaries are indeed ordered, I think from python 3.6 on?):
new_d = {kv[0]:kv[1] for i, kv in enumerate(d.items()) if i <= 4}

Categories