Returning a list of N dictionary keys that have the maximum integer values - python-3.x

my_dict = {'label': 6, 'label_2': 5, 'label_3': 9, 'label_4': 12}
I would like to create a list that will contain the top 2 (or 3, or 4, or 50... this will vary) dictionary keys, according to their highest values. So in the example above if I wanted the top 2, I should get:
['label_3', 'label_4']
for top 3 I should get:
['label', 'label_3', 'label_4']
And so on.
After reading some other stackoverflow threads, I've been experimenting with heapq, but can't get it to work the way I want. Would appreciate some help.

Of course, the moment I post here, I find a solution (thanks to the heapq documentation). This works:
my_list = heapq.nlargest(3, my_dict, key=my_dict.get)
This will go over my_dict and return the keys with the 3 largest values.
Thanks.

Related

'if' 'or'- statement in dictionary always returns TRUE

I have this python dictionary:
event_dict = {
'False': 1,
'Hit': 2,
'MP1': 3,
'MP2': 4,
'MP3': 5,
'M_False': 6,
'M_Hit': 7,
'OGT': 8,
'PMC': 9,
'S 4': 10,
'actiCAP Data On': 11,
'boundary': 12
}
And I wrote this code to check if the entries "TriEVE", "TriODD", "TriPMC" are in the dictionary (They're not!):
if "TriEVE" or "TriODD" or "TriPMC" in event_dict:
print('THIS SESSION HAS BAD ANNOTATIONS!!!!!!!')
The code returns:
THIS SESSION HAS BAD ANNOTATIONS!!!!!!!
I tried to use the 'if'-statement with just one input (without 'or'), like:
if "TriEVE" in event_dict:
print('THIS SESSION HAS BAD ANNOTATIONS!!!!!!!')
print(subject)
The code returns nothing, as expected.
Why can't I use 'or'-statements in this case? Is there a smarter way of searching for more than one dictionary entry at once?
In this case, you want
if "TriEVE" in event_dict.keys() or "TriODD" in event_dict.keys() or "TriPMC" in event_dict.keys():
this is because anything not-zero or non-None is evaluated to True in Python
Since it seems that you wanted to search the keys of the dict, you have to use .keys() or .values() if you want to look at values. The object itself isn't useful in this context

can't remove some duplicate elements from a list in python

well I was trying to remove duplicate items from a list so it has unique items and I also wanted to use for and if my code went so well but in one condition I faced something I don't understand. this is the example :
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a:
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
print(a)
[1, 21, 21, 16, 20, 7]
I don't understand why !! It removes 2,3,28 which was predicted but not 21 !
any help would be great , thanks.
The best solution for this case is using set(). If you do list(set(a)) it will remove all duplicates.
Notice that set() is not the same as list() so be sure to turn it back to a list if you want to keep using list methods.
About your code, the problem with your code is that you're running on the list as you're changing it.
While you run over the items the indexes changes and that's why you miss some of the items.
You can see more clearly what happens if you add a print to understand what's x's value:
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a:
print(x)
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
I believe your issue is that you are changing the list while you're looping over it
Try using a.copy() to create a new copy of the list to loop over like so.
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a.copy():
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
print(a)
This code will output
[1, 16, 20, 7]

Reorder a dictionary based on a list in python

Let's say I have a python dictionary {apple: 15, orange: 22, juice: 7, blueberry:19} and I want to reorder the dictionary according to the order of this list [juice, orange, blueberry, apple]. How would I do this cleanly/efficiently?
Note: the list could very well have more items than the dictionary.
O(n) method is to simply loop over your list of ordered keys:
{k: d[k] for k in keys}
If you want to maintain the same mutable reference to the dictionary (for whatever reason), just delete the key and add it in a loop. It will naturally order itself correctly.
As mentioned in the comments, dictionaries don't have an order in Python. Assuming you want to get the dictionary values in the same order as the list, you could do something like this. It checks to see if the key is in the dictionary first, so extra items in the list won't matter
d = {apple: 15, orange: 22, juice: 7, blueberry:19}
order = [juice, orange, blueberry, apple]
for key in order:
if key in d:
print(d[key])
Alternatively as #ewong mentioned, you can use an OrderedDict, which tracks the order a key is added. It seems like to re-order one you have to create a new OrderedDict, so in your case you could potentially create one from your original dictionary.
from collections import OrderedDict
ordered_d = OrderedDict([(key, d[key]) for key in order if key in d])

How to implement a custom sorting algorithm to accept any type in python?

If I have to implement the sort, how can I make it accept any type of data (a list, string, set, dictionary or my own class type) and sort it? (I have done it for list, though). I'm new to OOPS and I couldn't understand much of source code of sorted(), which is written in 'C'.
EDITS
Here is the code:
class InsertionSort:
def insertion_sort(it):
for i in range(len(it)):
j = i
while j > 0 and it[j] < it[j - 1]:
it[j], it[j-1] = it[j-1], it[j]
j -= 1
return it
it_ints = [9, 8, 7, 6, 5, 4, 3, 2, 1]
sorted_ints = InsertionSort.insertion_sort(it_ints)
Now, what if I wanna pass other data structures? I could convert them to list as one of the answers say, but, how to sort dictionary or other types of data
I'm looking for something like Comparable of Java
in Python to implement
PS: I'm actually doing Algorithms course on Coursera which is in JAVA. I'm trying to analyze the lectures there and re-write programs in python, particularly with class implementation.
Need help
Now that you've mentioned that you already have a function to sort list than why not try this?
def yourSortingFunction(items):
#now that you're expecting them to be list:
items = list(items)
//your sorting code
P.S: even sorted() function in python 3.x returns a list of sorted elements when you pass(list, set, string) and since you asked about these 3 in your question I'm suggesting this solution.
Comments and edits are most welcome. I'm new to StackOverflow (and coding).

Python3.4 Dictionary value replacement issue

I have some code which takes a list of dictionaries and creates another list of dictionaries.
Each dictionary in the list has two key/value pairs "ID" and "opcode", where "opcode" is a 32 bit number.
My code needs to create a second list of dictionaries where the opcodes are separated, i.e. a dictionary with opcode=5 would become two dictionaries with opcode=1 and opcode=4.
(opcode is a 32 bit number and my requirement is that only 1 bit is high, ie opcode=1,2,4,8,16 etc)
I've simplified the problem into the following; my code needs to turn this:
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
into this:
part_=[{"ID":1,"opcode":4},{"ID":2,"opcode":1},{"ID":2,"opcode":4},{"ID":3,"opcode":2},{"ID":3,"opcode":4}]
Currently my code is the following
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
The output of the code is:
{'opcode': 4, 'ID': 1}
{'opcode': 1, 'ID': 2}
{'opcode': 2, 'ID': 3}
Interestingly if I modify the code slightly so that the value modification line is not there, the extra dictionaries are created, but obviously the opcode is not correct.
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
#part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
The output is
{'ID': 1, 'opcode': 4}
{'ID': 2, 'opcode': 5}
{'ID': 2, 'opcode': 5}
{'ID': 3, 'opcode': 6}
{'ID': 3, 'opcode': 6}
I can get around the issue by going about the problem a different way, but in the interest in learning what is going on I'm out of my depth.
This is caused as when you append i to the new list you do not create a copy of the dictionary instead you add a reference to the original dictionary. This means that when you change the dictionary in the next line you also change value in part. This causes the loop not to match the any more parts of the opcode. You can see this if you print out the values of part at the end of your code.
The python documentation explains this as:
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
Reference
You can fix this by creating a copy of the dictionary when you append it. This will allow you change the value without affecting the original dictionary. Python allows you to copy objects using the copy module (Documentation).
Just import copy and then do part_.append(copy.copy(i)) instead of part_.append(i).
import copy
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part = [{"ID": 1, "opcode": 4}, {"ID": 2, "opcode": 5}, {"ID": 3, "opcode": 6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(copy.copy(i))
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)

Resources