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.
Related
I have a list that is of the following form:
my_list= [['A',(3,4)],['A2',(6,11)],['U1',(2,9)],['P9',(1,9)], ['X',(10,4)]...]
I need to sort the letter/number combinations based on the list that corresponds with them, (1,2,3,4) for example.
The second number in the list needs to be in descending order. Then, the first number in that list needs to be in descending order. The last number takes priority over the first number.
These numbers correspond to the location of these values on an image. I am attempting to sort these by the way they appear on the image (top to bottom, left to right).
The correct order for the above list would be:
['A2',(6,11)], ['U1',(2,9)],['P9',(1,9)], ['X',(10,4)], [['A',(3,4)]
To be frank, I do not know where to start with this. Could someone please explain how to properly write this in Python?
You can pass a key function to list.sort to specify what to sort by.
my_list.sort(key=lambda x: (-x[1][1], -x[1][0]))
In general: to sort by multiple keys, if you have a stable sort (and Python's sort is stable), then you can do it in steps from the least important key to the primary key. In your case by the first number descending and then by the second number also descending:
s0 = [['A',(3,4)],['A2',(6,11)],['U1',(2,9)],['P9',(1,9)], ['X',(10,4)]]
s1 = sorted(s0, key = lambda x: x[1][0], reverse=True)
print(s1) # intermediate result
s2 = sorted(s1, key = lambda x: x[1][1], reverse=True)
print(s2) # final result
so I have a defaultdict(list) hashmap, potential_terms
potential_terms={9: ['leather'], 10: ['type', 'polyester'], 13:['hello','bye']}
What I want to output is the 2 values (words) with the lowest keys, so 'leather' is definitely the first output, but 'type' and 'polyester' both have k=10, when the key is the same, I want a random choice either 'type' or 'polyester'
What I did is:
out=[v for k,v in sorted(potential_terms.items(), key=lambda x:(x[0],random.choice(x[1])))][:2]
but when I print out I get :
[['leather'], ['type', 'polyester']]
My guess is ofcourse the 2nd part of the lambda function: random.choice(x[1]). Any ideas on how to make it work as expected by outputting either 'type' or 'polyester' ?
Thanks
EDIT: See Karl's answer and comment as to why this solution isn't correct for OP's problem.
I leave it here because it does demonstrate what OP originally got wrong.
key= doesn't transform the data itself, it only tells sorted how to sort,
you want to apply choice on v when selecting it for the comprehension, like so:
out=[random.choice(v) for k,v in sorted(potential_terms.items())[:2]]
(I also moved the [:2] inside, to shorten the list before the comprehension)
Output:
['leather', 'type']
OR
['leather', 'polyester']
You have (with some extra formatting to highlight the structure):
out = [
v
for k, v in sorted(
potential_terms.items(),
key=lambda x:(x[0], random.choice(x[1]))
)
][:2]
This means (reading from the inside out): sort the items according to the key, breaking ties using a random choice from the value list. Extract the values (which are lists) from those sorted items into a list (of lists). Finally, get the first two items of that list of lists.
This doesn't match the problem description, and is also somewhat nonsensical: since the keys are, well, keys, there cannot be duplicates, and thus there cannot be ties to break.
What we wanted: sort the items according to the key, then put all the contents of those individual lists next to each other to make a flattened list of strings, but randomizing the order within each sublist (i.e., shuffling those sublists). Then, get the first two items of that list of strings.
Thus, applying the technique from the link, and shuffling the sublists "inline" as they are discovered by the comprehension:
out = [
term
for k, v in sorted(
potential_terms.items(),
key = lambda x:x[0] # this is not actually necessary now,
# since the natural sort order of the items will work.
)
for term in random.sample(v, len(v))
][:2]
Please also see https://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/ to understand how the list flattening and result ordering works in a two-level comprehension like this.
Instead of the out, a simpler function, is:
d = list(p.values()) which stores all the values.
It will store the values as:
[['leather'], ['polyester', 'type'], ['hello', 'bye']]
You can access, leather as d[0] and the list, ['polyester', 'type'], as d[1]. Now we'll just use random.shuffle(d[1]), and use d[1][0].
Which would get us a random word, type or polyester.
Final code should be like this:
import random
potential_terms={9: ['leather'], 10: ['type', 'polyester'], 13:['hello','bye']}
d = list(p.values())
random.shuffle(d[1])
c = []
c.append(d[0][0])
c.append(d[1][0])
Which gives the desired output,
either ['leather', 'polyester'] or ['leather', 'type'].
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())))
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.
I have a nested dictionary of type following
{id_1 : [ {id_2:score},{id_3:score_2} .... and so on],id_2 :[{id_1:Score_!....]}
so basically a nested dictionary
Now I want to sort this dictionary per primary id on the basis of score
so basically
{id_1: [{element with max_score},{element_with next max_score....}]... id_2:[{element_with max_score},{element_with next maxx score}...]
also, the function should take an argument say (n) which returns the top n matches or if the n< number of elements of that id then it returns teh complete list
any Ideas/ thoughts..
Thanks
You can use the key parameter to list.sort(). Assuming the outer dictionary is called d, the code could look like this:
for scores in d.itervalues():
scores.sort(key=lambda x: next(x.itervalues()), reverse=True)
The lambda function simply extracts the single value of the dictionary.
I think you'd be better off using tuples instead of dictionaries as the values of your list:
{id_1: [(id_2, score_2), (id_3, score_3),...], id_2: [(id_1, score_1),...]}
Using this data structure, the sorting code would be
for scores in d.itervalues():
scores.sort(key=lambda x: x[1], reverse=True)
or equivalently, but slightly faster
for scores in d.itervalues():
scores.sort(key=operator.itemgetter(1), reverse=True)