find key in dictionary with n-th largest value - python

given a dictionary like this: example_dict ={"mark":13, "steve":3, "bill":6, "linus":11}
finding the key with max value is easy using max(example_dict.items(), key=operator.itemgetter(1)) and min value using min(example_dict.items(), key=operator.itemgetter(1))
What's the easiest way to find the key with the n-th largest value? e.g. the key with the 2nd largest value here is linus

Use nlargest:
import heapq
example_dict ={"mark":13, "steve":3, "bill":6, "linus":11}
*_, res = heapq.nlargest(2, example_dict, key=example_dict.get)
print(res)
Output
linus
From the documentation:
Return a list with the n largest elements from the dataset defined by
iterable. key, if provided, specifies a function of one argument that
is used to extract a comparison key from each element in iterable (for
example, key=str.lower).
A note on performance, also from the documentation:
perform best for smaller values of n. For
larger values, it is more efficient to use the sorted() function.
Also, when n==1, it is more efficient to use the built-in min() and
max() functions. If repeated usage of these functions is required,
consider turning the iterable into an actual heap.
Note that it returns a list, that is why you discard the first n-1 elements

Use QuickSelect algorithm. It works in O(n) on average

Something like this:
def nth_largest_key(di, n):
sorted_items = sorted(di.items(), key=lambda item: item[1],
reverse=True)
return sorted_items[n-1][0]
input_di = {"mark":13, "steve":3, "bill":6, "linus":11}
print(nth_largest_key(input_di, int(input().strip())))

Related

What [k] is in python sorting with lambda function?

I don't understand the lambda k function, and especially, what is the last [k] in this line of code?
sorting_permutation = sorted(range(len(prediction_test[0:m_test])), key=lambda k: prediction_test[0:m_test][k])
I am so sorry for my English.
We should analyse the whole function. You want to sort range(len(prediction_test[0:m_test])) . Assuming m_test isn't greater than len(prediction_test) , this should give a list containing numbers from 0 to m_test-1 .
Key parameter of sorting function defines the function that the list is accordingly sorted. k values are the elements of the list that you want to sort. In your code, k will take values 0,1,2...,m_test-1 under the assumption. With prediction_test[0:m_test][k] you first take a slice of prediction_test from index 0 to index m_test, then you take the element at kth index.
In a nutshell,
key=lambda k: prediction_test[0:m_test][k] means that you will sort your list according to results of prediction_test[0:m_test][k] where k will take values of your elements in the list. Your code is probably used for sorting the indices of a list according to values that they store.

Find indices of x minimum values of a list

I have a list of length n.
I want to find the indices that hold the 5 minimum values of this list.
I know how to find the index holding the minimum value using operator
min_index,min_value = min(enumerate(list), key=operator.itemgetter(1))
Can this code be altered to get a list of the 5 indices I am after?
Although this requires sorting the entire list, you can get a slice of the sorted list:
data = sorted(enumerate(list), key=operator.itemgetter(1))[:5]
if use package heapq, it can be done by nsamllest:
heapq.nsmallest(5, enumerate(list), key=operator.itemgetter(1))
what about something like this?
map(lambda x: [a.index(x),x],sorted(list)[:5])
that will return a list of lists where list[x][0] = the index and list[x][1] = the value
EDIT:
This assumes the list doesn't have repeated minimum values. As adhg McDonald-Jensen pointed out, it this will only return the first instance of the give value.

Keyword functions for Python min/max

I am trying to understand how this works:
my_dict = {'a':2,'b':1}
min(my_dict, key=my_dict.get)
produces
b
Which is a really cool feature and one I want to understand better.
Based on the documentation
min(iterable[, key])
Return the smallest item in an iterable or the smallest of two or more arguments...
The optional key argument specifies a one-argument ordering function like that used for list.sort(). The key argument, if supplied, must be in keyword form (for example, min(a,b,c,key=func)).
Where can I find out more about available functions? In the case of a dictionary, is it all the dictionary methods?
Edit: I came across this today:
max(enumerate(array_x), key=operator.itemgetter(1))
Still looking for information on available keyword functions for min/max
The code you have written is
my_dict = {'a':2,'b':1}
min(my_dict, key=my_dict.get)
actually this works on min function.
so, what does min do?
min(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its lowest item. With two or more arguments, return the lowest argument.
The key here is used to pass a custom comparison function.
Example: output max by length of list, where arg1, arg2 are both lists.
>>>> max([1,2,3,4], [3,4,5], key=len)
[1, 2, 3, 4]
But what if I want the max from the list, but by considering the second element of the tuple? here we can use functions, as given in official documentation. The def statements are compound statements they can't be used where an expression is required, that's why sometimes lambda's are used.
Note that lambda is equivalent to what you'd put in a return statement of a def. Thus, you can't use statements inside a lambda, only expressions are allowed.
>>> max(l, key = lambda i : i[1])
(1, 9)
# Or
>>> import operator
>>> max(l, key = operator.itemgetter(1))
(1, 9)
so the functions are basically depend upon the the iterable and and passing the criteria for the comparison.
Now in your example, you are iterating over your dictionary. And in key, you are using get method here.
The method get() returns a value for the given key. If key is not available then returns default value None.
As here, no arguments are there in get method it simply iterates over values of dictionary. And thus the min gives you the key having minimum value.
For max(enumerate(array_x), key=operator.itemgetter(1))
we want to compare the values of array instead of their indices. So we have enumerated the array.
enumerate(thing), where thing is either an iterator or a sequence, returns a iterator that will return (0, thing[0]), (1, thing1), (2, thing[2])
now we have used itemgetter function of operator module. operator.itemgetter(n) constructs a callable that assumes an iterable object (e.g. list, tuple, set) as input, and fetches the n-th element out of it.
you can also use lambda function of here like
max(enumerate(array_x), key=lambda i: i[1])
So the range of functions in key is almost up to the use. we can use many functions but the sole motive is , it is the criteria for that comparison.
Imagine you have objects with some attribute you want to use to get the minimum value:
min(my_objects, key=lambda x: x.something)
This will give you the object with the smallest something attribute.
The same thing exists for example in sorted() so you can easily sort by a value derived from the object. Imagine you have a list of people and want to sort by first name, then last name:
people.sort(key=lambda x: (x.first_name, x.last_name))

How to order a list of tuples by the integer value of a certain index of each, in Python?

Given a list of tuples e.g.
[('a','b','4'),('c','d','9'),('e','f','2')]
The third element of each tuple will always be the string value of an integer.
I want to write each tuple as a row of a csv using csv.writerow().
Before I do, I want to reorder the tuples (ideally by overwriting the existing list or creating a new one) such that they get written in descending order of the integer value of that third element of each e.g.
c,d,9
a,b,4
e,f,2
I'm trying to imagine some sort of multiple if/else combo in a list comprehension, but surely there's go to be a simpler way?
The sorted function (or the list method sort) takes optional arguments reverse to allow you to sort in decreasing order, and key to allow you to specify what to sort by.
l = [('a','b','4'),('c','d','9'),('e','f','2')]
l.sort(key=lambda x: int(x[2]), reverse=True)
gives you the list in the order you want.
In my answer I use sys.stdout as an example but you may use a file instead
>>> import sys, csv
>>> items = [('a','b','4'),('c','d','9'),('e','f','2')]
>>> w = csv.writer(sys.stdout)
>>> w.writerows(sorted(items, key=lambda x: int(x[2]), reverse=True))
c,d,9
a,b,4
e,f,2
This works in both Python 2 and Python 3:
x = [('a','b','4'),('c','d','9'),('e','f','2')]
x.sort(key=lambda int(x:x[2]), reverse=True)
key is a function applied to each item in the list and returns the key to be used as the basis for sorting.
Another one using itemgetter slightly faster than lambda x: x[2] for small lists and considerably faster for larger lists.
from operator import itemgetter
l = [('a','b','4'),('c','d','9'),('e','f','2')]
l.sort(key=itemgetter(2), revese=True)
Python sorting mini Howto has got a lot many useful tricks worth reading.
Slightly different, albeit less efficient solution:
def sort_tuple_list(l):
sorted_ints = sorted([int(i[2]) for i in l], reverse=True)
sorted_tuple_list = []
for i in sorted_ints:
for tup in l:
if int(tup[2]) == i:
sorted_tuple_list.append(tup)
return sorted_tuple_list
Returns a list sorted according to the original question's specifications.
You can then simply write each row of this returned list to your csv file.

Getting the key to the maximum component of a tuple in a dictionary of tuples

I have a dictionary whose components are all 2-tuples (all integers) and I want to find the key to the tuple with the largest second component. How can I do this in Python 2.6?
The following will do it (where d is your dictionary):
max(d.items(), key=lambda(k,v):v[1])[0]
In this solution, the key (if you pardon the pun) is to use the optional key argument to max.
aix' answer is a good one. You can achieve the same without using lambdas if you prefer, though:
import operator
m = max(d.iteritems(), key=operator.itemgetter(1))[0]

Categories