sort dictionary of objects - python

I have a dictionary of objects where the key is a simple string, and the value is a data object with a few attributes. I'd like to sort my dictionary based on an attribute in the values of the dictionary. i have used this to sort based on the dictionaries values
sorted = dict.values()
sorted.sort(key = operator.attrgetter('total'), reverse=True)
This yields a sorted list of values (which is expected) and I lose my original keys from the dictionary (naturally). I would like to sort both the keys and values together... how can I achieve this? Any help would be greatly appreciated?

Use .items() (or its iterator version iteritems) instead of .values() to get a list of (key, value) tuples.
items = sorted(dct.iteritems(), key=lambda x: x[1].total, reverse=True)

You'll want to use .items() rather than .values(), for example:
def keyFromItem(func):
return lambda item: func(*item)
sorted(
dict.items(),
key=keyFromItem( lambda k,v: (v['total'], k) )
)
The above will sort first based on total, and for items with equal total, will sort them alphabetically by key. It will return items as (key,value) pairs, which you could just do [x[1] for x in sorted(...)] to get the values.

Use items instead of values - and a just use a lambda to fecth the sorting key itself, since there won't be a ready made operator for it:
sorted = dict.items()
sorted.sort(key = lambda item: item[1].total, reverse=True)

Related

Iterating over a python dictionary?

I have a dictionary where the keys are integers and the values are strings. The dictionary has been sorted using key values.
I need to copy the corresponding string values (keeping the sorted order) to a list. I cannot figure out how to iterate over the dictionary.
I know the number of key-value pairs in the dictionary (let it be 'n').
Some_ordered_dict
resultant_list=[]
for i in range(n):
resultant_list.append(Some_ordered_dict[increment-key?]
The dictionary was sorted using OrderedDict from some dictionary 'dic' as follows;
od=collections.OrderedDict(sorted(dic.items()))
The essential point is that I have to display the strings values of the dictionary in the same order as they appear in the sorted dictionary.
resultant_list = [d[k] for k in sorted(d)]
The standard Python dictionary does not guarantee that items in a dictionary will be kept in any order. Next thing is that you have to iterate using a "for in" statement like such:
Some_ordered_dict
resultant_list=[]
for i in Some_ordered_dict:
resultant_list.append(Some_ordered_dict[i])
You should take a look at the ordered dict collection to ensure that the items on your dict are kept in the order that you expect.
Using the standard unordered dictionary in python you could use something like this:
resultant_list = []
for i in sorted(dict.keys()):
resultant_list.append(dict[i])
As mentioned in other posts, dictionaries do not guarantee order. One way to get a sorted list would be to created a list of tuples out of your dict's (key, value) pairs, then sort this list based n the first element(the key), as follows:
my_dict = {2: 'two', 3: 'three', 1: 'one'}
my_tuple_list = list(zip(my_dict.keys(), my_dict.values()))
my_sorted_list = sorted(my_tuple_list, key = lambda item: item[0])
resultant_list = [x[1] for x in my_sorted_list]

Sorting values in multiple lists

Currently, I have a list of lists called result which will contain values like this, for example:
result[1] = [John, 0.32]
result[2] = [Mikey, 1.90]
result[3] = [Sarah, 1.31]
result[4] = [Nancy, 0.49]
result[5] = [Billy, 0.13]
I want to however, sort this in descending order by the number which is held in the index space [1]. So the system will return the values in that order. Would I just have to use the sorted() function and call up the index where the value is held? I do not need to resort the list is it is necessary, i will just need to output the values in descending order.
How would I go about doing this exactly?
Use the key parameter in the sorted function.
sorted(result, key = lambda x:x[1], reverse = True)
The reverse = True makes sure that the items are sorted in the descending order. The important thing to be noted here is the key parameter.
key = lambda x:x[1]
We pass a lambda function to the key parameter, which accepts one parameter. sorted picks each element from result and pass that to the key function. In our case it is the tuples. The key function returns the second item in the tuples. So, the second item in the tuple will be used as the value of the tuple itself, while sorting. It means that when we comapre [John, 0.32] and [Mikey, 1.90], we will be actually comparing 0.32 and 1.90 only.
sorted doesn't change the actual list, but creates a new sorted list. But, if you want to sort the list itself, then you can use list.sort method, like this
result.sort(key = lambda x:x[1], reverse = True)
You can do that using sorted:
new_list = sorted(old_list, key=lambda x: x[1], reverse=True)
or using sort:
old_list.sort(key=lambda x: x[1], reverse=True)

Iterating through a dictionary for X number of times

Assume the dictionary contains more than 10 key-value pairs. The dictionary ought to be sorted by values (of integers). Print out the top 10 values (and corresponding keys). I think there is a better solution that what I have given here.
for keys in sorted(x):
c=c+1
if c>10:
break
else:
print keys, x['keys']
for key in sorted(x, key=x.get, reverse=True)[:10]:
print key, x[key]
For really large dict you should consider using a heapq
from heapq import nlargest
for key in nlargest(10, x, key=x.get):
print key, x[key]
There is no order defined on dictionary keys, so the "first" keys are not well defined. Specifically, what you did is easier done with x.keys()[:10].
topten = sorted(x.items(), key=lambda x:-x[1])[:10]
You can iterate over dict for X number of times using the following code.
Python 3.8
def highest_contributor(self, top=1):
slice_dict_only_to_keys = list(self.contributors.keys())[:top]
for _key in slice_dict_only_to_keys:
self.log("Top Contributor: {} ({})".format(_key, self.contributors[_key]))
Don't worry about integers and incrementing them with your code. You don't need them.
Simple, readable and Maintainable.

Sort keys in dictionary by value in a list in Python

I have seen this post and this post as well as many others, but haven't quite found the answer to my question nor can I figure it out.
I have a dictionary of lists. For example it looks like:
Dict = {'a':[1,2,3,4], 'b':[9,8,7,6], 'c':[8,5,3,2]}
I want to return a list of the keys sorted (descending/reverse) based on a specific item in the lists. For example, I want to sort a,b,c based on the 4th item in each list.
This should return the list sorted_keys = ['b','a','c'] which were sorted by values [6,4,2].
Make sense? Please help...thanks!
Supply a key function, a lambda is easiest, and sort reversed:
sorted(Dict.keys(), key=lambda k: Dict[k][3], reverse=True)
The key function tells sorted what to sort by; the 4th item in the value for the given key.
Demo:
>>> sorted(Dict.keys(), key=lambda k: Dict[k][3], reverse=True)
['b', 'a', 'c']

Sorting a dict with tuples as values

I have a dictionary that looks like this:
{'key_info': (rank, raw_data1, raw_data2),
'key_info2': ...}
Basically I need back a list of the keys in sorted order, that is sorted based on the rank field in the tuple.
My code looks something like this right now (diffs is the name of the dict above):
def _sortRanked(self):
print(type(self.diffs))
return sorted(self.diffs.keys(), key=lambda x: x[1], reverse=True)
that right now returns this when I run it:
return sorted(self.diffs.keys(), key=lambda x: x[1], reverse=True)
IndexError: string index out of range
keys() only gives you keys, not values, so you have to use the keys to retrieve values from the dict if you want to sort on them:
return sorted(self.diffs.keys(), key=lambda x: self.diffs[x], reverse=True)
Since you're sorting on rank, which is the first item in the tuple, you don't need to specify which item in the value tuple you want to sort on. But if you wanted to sort on raw_data1:
return sorted(self.diffs.keys(), key=lambda x: self.diffs[x][1], reverse=True)
You're passing the key as the argument to, uh, key.
[k for (k, v) in sorted(D.iteritems(), key=lambda x: x[1], reverse=True)]
You're attempting to sort on the keys of the dictionary, not the values. Replace your self.diffs.keys() call with self.diffs.items(), and then it should work (but do keep the lambda, or use operator.itemgetter(1). Tuples sort starting with the first element, so you don't have to worry about that.)
Just noticed that you only want the keys. With my suggestion, you'd have to wrap the sort with zip()[0] (making sure to unpack the resultant list of tuples from the sort by prefixing with * in the call to zip()).
You're close. Try this instead:
return sorted(self.diffs.keys(), key = lambda x: self.diffs[x][0], reverse = True)
You're sorting a list of keys, so you have to take that key back to the dictionary and retrieve element 1 in order to use it as a comparison value.

Categories

Resources