I have a dictionary, "scores", of integers and I want to find the key(s) of the highest value. I used this code:
key = max(scores, key=scores.get)
however, this only gives back one key. How does this deal with ties in highest value? I only get one number back. Which is it in the case of a tie? How can I get all the keys to the highest value?
Thanks for your help.
You could run the following, for example:
max_value = max(scores.values())
keys = [ i for (i,v) in scores.iteritems() if v == max_value ]
"keys" would now hold all the keys which correspond to the maximum value.
scores = dict(a=1,b=2,c=3,d=4,e=5,f=5)
maxscr = max(scores.values())
maxscrs = [scr for scr in scores if scores[scr]== maxscr]
gives:
['e','f']
max_value = max(scores, key=scores.get)
keys = [score for score in scores if scores[score] == max_value]
The max function returns one value. You could use something like this:
key = max(scores, key=scores.get)
keys = [k for k in scores if scores[k] == scores[key]]
Edit: fixed
Related
Hi I want to write a python function to find all lowest scorers in dictionary with time complexity of o(n).
The function should handle 2nd lowest value in any index of dictionary including the first k,v pairs.
function should handle duplicate lowest scores too.
Testcase:
second_lowest_scorers({"hri":6.2,"dav":1.1,"asv":1.1,"wrs":12.3,"dup":6.2,"awe":43.2,"asw":22.2,"asd":6.2})
expected output:
['asd', 'dup', 'hri'] (optional: sorted by name)
Explanation asv and dav scored 1.1 which is lowest score. asd,dup,hri scored next lowest.
I have so far solved it using multiple loops.
def lowest_scores(names_scores):
lowest_score=min(names_scores.values())
lowscorers=[]
low_scorer_dict = { k : v for k,v in names_scores.items() if v != lowest_score}
second_lowest_score = min(low_scorer_dict.values())
for k,v in low_scorer_dict.items():
if v == second_lowest_score:
lowscorers.append(k)
return sorted(lowscorers)
Dont want to use external functions like to solve algorithmic way possible
O(N) solution
data = {"hri":6.2,"dav":1.1,"asv":1.1,"wrs":12.3,"dup":6.2,"awe":43.2,"asw":22.2,"asd":6.2}
vals = set(data.values()) # create set so we don't get duplicates
vals.remove(min(vals)) # remove the most minimum
minVal = min(vals) # this is the second minimum
for k,v in data.items():
if v == minVal :
print(k) # where value is second minimum
hri
dup
asd
I have a whole program that has a previous dictionary in a different function that gives me a list of departure and arrival cities for planes.
I am trying to write a function that determines which keys have the most outgoing flights and I am unable to figure out how to find which keys have the most values. My dictionary is named flights which has the departure city as the keys and the arrivals as values.
def outgoing(flights):
length = 0
for i in (flights):
if (len(flights[i]) > length):
length = (len(flights[i]))
break
else:
continue
for i in flights:
if (len(flights[i]) == length):
pop = (len(flights[i]))
print ("the most outgoing flight is: " , [i])
this code is suppose to work but for some reason it isn't giving me the correct max output from the file. Any ideas as to why?
The simplest solution is to just use the builtin max function and list comprehension:
def outgoing(flights):
print(max([len(i) for i in flights]))
If you want to stick with your code, you need to compare to the max each iteration:
def outgoing(flights):
max_outgoing = 0
for i in flights:
if(max_outgoing < len(flights[i])):
print(max_outgoing)
max_outgoing = len(flights[i])
EDIT: On re-reading your question, it seems that you'd also like to get the key of the max value. The just do this:
def outgoing(flights):
max_outgoing = 0
max_key = None
for i in flights:
if(max_outgoing < len(flights[i])):
print(max_outgoing)
max_outgoing = len(flights[i])
max_key = i
Or in the shorter version:
def outgoing(flights):
out_dict = {i: len(i) for i in flights}
max_out = max(out_dict, key=out_dict.get)
print(max_out)
print(flights[max_out])
You weren't very clear about the structure of flights, so I'm going to assume it's a the keys are strings and the values are lists of strings.
One way to do this would be to create a list of tuples, where each element is (departure_city, len(flights[departure_city])). Then you can sort the list by number of arrivals.
def outgoing(flights):
# Create a list of tuples
flight_tups = [(departure_city, len(flights[departure_city])) for departure_city in flights]
# Sort the list by number of arrivals
# We do this by passing a lambda to `sort`,
# telling it to sort by the second value in
# each tuple, i.e. arrivals
flight_tups.sort(key=lambda tup: tup[1])
# We can now get the city with the most arrivals by
# taking the first element of flight_tups
most = flight_tups[0]
print(f'City: {most[0]}\nNumber of Arrivals: {most[1]}')
Note: you can also use max, but from your question it seemed like you wanted
the cities with the most arrivals, not just the one city with the most. Using sort will also let you tell if there's a tie.
My function needs to find the character with the highest speed in a dictionary. Character name is the key and value is a tuple of statistics. Speed is index 6 of the value tuple. How do I compare the previous highest speed to the current value to see if it is higher? Once I get the speed, how can I take that character's types (index 1 and 2 in value tuple,) and return them as a list?
Example Data:
d={'spongebob':(1,'sponge','aquatic',4,5,6,70,6), 'patrick':(1,'star','fish',4,5,6,100,1)}
Patrick has the highest speed(100) and his types are star and fish. Should return [star,fish]
Here is my current code which doesn't work since I don't know how to compare previous and current:
def fastest_type(db):
l=[]
previous=0
new=0
make_list=[[k,v] for k,v in db.items()]
for key,value in db.items():
speed=value[6]
return l_types.sort()
The sorted function can do this quite easily:
Code:
from operator import itemgetter
def fastest_type(db):
fastest = sorted(db.values(), reverse=True, key=itemgetter(6))[0]
return fastest[1], fastest[2]
This code sorts by key 6, in reverse order so that the largest is first, and then set fastest to the first element of the sort. Then it simply returns the two desired fields from fastest.
Test Code:
d = {
'spongebob':(1,'sponge','aquatic',4,5,6,70,6),
'patrick':(1,'star','fish',4,5,6,100,1)
}
print(fastest_type(d))
Results:
('star', 'fish')
If I understood what you meant.
def fastest_type(db):
speed = 0
new = []
for key,value in db.items():
if speed < value[6]:
speed = value[6]
new = value[1:3]
return list(new) # return list instead of tuple
I have a problem with the max() function of python.
Here's my situation :
results = {'left' : leftKeyCounter, 'right' : rightKeyCounter, 'front' : frontKeyCounter, 'back' : backKeyCounter}
finalScore = max(results, key=results.get)
print(finalScore, 'wins')
The problem I have is to make if conditions on what's happening with my results. Let's say, I have
results = {'left' : 1, 'right' : 1, 'front' : 1, 'back': 0}
The fact that he will return 'front wins' on this is completely random, and I need to filter over that result. (or before?)
So that if it's a draw between the 2 highest results, that he cancels it (for example)
What could be the easiest way to make that possible ? I looked into the "counter" but that doesn't achieve what I intend to do here, as my numbers are already packed and I just need to compare 4 values, without any tie between the 2 highests value.
Thanks a lot ! :-)
With one pass over the dictionary you can figure out the correct result. Reverse the keys with the values and keep a track of the highest score. If there is more than one items for the highest score, you can return a custom message.
In reversing, you can't simply do {value: key for key, value in results.items()}, because if two values are the same, they will overwrite the previous one. So you have to keep the results in a list. Credits to chepner for scores.setdefault(). He also suggested that the same can be achieved with collections.defaultdict().
def calculate_winner(d):
scores = {}
high_score = 0
for key, value in d.items():
scores.setdefault(value, []).append(key)
if value > high_score:
high_score = value
results = scores[high_score]
if len(results) == 1:
return results[0]
else:
return 'TIE', results
Example:
>>> calculate_winner(results)
('TIE', ['front', 'right', 'left'])
Edit: If you have a small dictionary, you can achieve the same result with fewer lines of code by doing two passes: one to find the max score and one to filter out the winners.
def calcaluate_winner(d):
max_value = max(d.values())
winners = [key for key in d if d[key] == max_value]
if len(winners) == 1:
return winners[0]
else:
return 'TIE', winners
I have a dictionary structure that maps an id (integer) into a number (double). The numbers are actually weights of an item.
I am writing a function that will allows me to fetch the id of a given weight (if the weight is found in the dict, else, it will return the id of the next closest (i.e. nearest matching) weight.
This is what I have so far:
def getBucketIdByValue(bucketed_items_dict, value):
sorted_keys = sorted(bucketed_items_dict.keys())
threshold = abs(bucketed_items_dict[sorted_keys[-2]] -bucketed_items_dict[sorted_keys[-1]]) # determine gap size between numbers
# create a small dict containing likely candidates
temp = dict([(x - value),x] for x in bucketed_items_dict.values() if abs(x - value) <= threshold)
print 'DEBUG: Deviations list: ', temp.keys()
smallest_deviation = min(temp.keys()) if value >= 0 else max(temp.keys()) # Not sure about this ?
smallest_deviation_key = temp[smallest_deviation]
print 'DEBUG: found bucketed item key:',smallest_deviation_key
return smallest_deviation_key
I'm not sure the logic is actually correct (esp. where I obtain the smallest deviatioon). In any event, if even the logic is correct, this seems an overly complicated way of doing things. Is there a more elegant/pythonic way of doing this?
Off the top of my head, I think a more pythonic/elegant way would be to do something like passing a custom function to the min function - don't know if that is possible...
[[Update]]
I am running Python 2.6.5
Try sorting the items by the distance of their weight to your target value:
from operator import itemgetter
distances = ((k, abs(v - value)) for k, v in bucketed_items_dict.items())
return min(distances, key=itemgetter(1))[0]
Or using a lambda function instead of itemgetter:
distances = ((k, abs(v - value)) for k, v in bucketed_items_dict.items())
return min(distances, key=lambda x:x[1])[0]
def getBucketIdByValue(bucket, value):
distances = [( id , abs( number - value ) ) for id , number in bucket.items()]
swapped = [( distance , id ) for id , distance in distances]
minimum = min ( swapped )
return minimum[1]
Or in short:
def getBucketIdByValue(bucket, value):
return min((abs(number-value),id) for id,number in bucket.items())[1]
This function uses the bucket to create id/number pairs, then creates an iterator of distance/id pairs, then gets the first minimum pair of it and finally extract the id of that pair and returns it.
The distance is defined as the absolute value of the difference between the number and the sought-for value.
The minimum is defined as the pair with the lowest distance. If there are more, the pair with the lowest id is returned.
You can find the index of closest weight using bisect in sorted keys:
import bisect
def bisect_weight(sorted_keys, value):
index = bisect.bisect(sorted_keys, value)
# edge cases
if index == 0: return sorted_keys[0]
if index == len(sorted_keys): return sorted_keys[index - 1]
minor_weight = sorted_keys[index - 1]
greater_weight = sorted_keys[index]
return minor_weight if abs(minor_weight - value) < abs(greater_weight - value) else greater_weight
This way you just need to check 2 weights and find the best one. Sorting and binary searching are probably faster than calc all weights and find the best one.
I'd also consider the bisect module.