Pythonic way with more than one max possible

C

CM

I have three items in a dict, like this:

the_dict = {'a':1, 'b':2, 'c':3}

but the vals could be anything. I want to configure something else
based on the "winner" of such a dict, with these rules:

1. In this dict, if there is a UNIQUE max value, that's the winner.
2. If there are any TIES for max value, b is the winner by default.

The problem for me, as I see it, is I don't know any elegant ways to
do this in Python. The max(dict) function doesn't distinguish between
unique and non-unique maxes. I could go through and test the various
possibilities (to see if the max value had any matches in the other
values), but, knowing Python, there is probably something close to
"one way to do it". Any suggestions?

Thanks,
Che
 
S

Steven D'Aprano

I have three items in a dict, like this:

the_dict = {'a':1, 'b':2, 'c':3}

but the vals could be anything. I want to configure something else
based on the "winner" of such a dict, with these rules:

1. In this dict, if there is a UNIQUE max value, that's the winner.
2. If there are any TIES for max value, b is the winner by default.

The problem for me, as I see it, is I don't know any elegant ways to
do this in Python. The max(dict) function doesn't distinguish between
unique and non-unique maxes. I could go through and test the various
possibilities (to see if the max value had any matches in the other
values), but, knowing Python, there is probably something close to
"one way to do it". Any suggestions?

# Untested.
def get_winner(adict):
values = sorted(adict.values(), reverse=True)
if values[0] == values[1]:
return adict['b']
else:
return values[0]

Assumes that adict has at least two items. May be slow if it has millions of
items.
 
C

Chris Rebert

I have three items in a dict, like this:

the_dict = {'a':1, 'b':2, 'c':3}

but the vals could be anything.  I want to configure something else
based on the "winner" of such a dict, with these rules:

1. In this dict, if there is a UNIQUE max value, that's the winner.
2. If there are any TIES for max value, b is the winner by default.

Er, for (2), you mean b's /value/ is the winner, right?
The problem for me, as I see it, is I don't know any elegant ways to
do this in Python.  The max(dict) function doesn't distinguish between
unique and non-unique maxes.  I could go through and test the various
possibilities (to see if the max value had any matches in the other
values), but, knowing Python, there is probably something close to
"one way to do it".  Any suggestions?

# presumes at least 2 items
from heapq import nlargest
winner, runner_up = nlargest(2, the_dict.itervalues())
if winner == runner_up:
winner = the_dict['b']

Cheers,
Chris
 
C

CM

I have three items in a dict, like this:

the_dict = {'a':1, 'b':2, 'c':3}

but the vals could be anything.  I want to configure something else
based on the "winner" of such a dict, with these rules:

1. In this dict, if there is a UNIQUE max value, that's the winner.
2. If there are any TIES for max value, b is the winner by default.

Thank you to Steven and Chris for the answers. Very elegant.

I realize, now though, (and Chris asked about this) that I was
imprecise in my
rules. They really should be stated as:

1. In this dict, if there is a UNIQUE max value, then its *key* is the
winner.
2. If there are any TIES for max value, then the *key* 'b' is the
winner by default.

The point is, I am trying to determine the name of the winning
category, either
'a', 'b', or 'c', not the value of its winning score.

So in your solutions there is sorting by values, which makes sense.
But how
can I go back to keys from there? Sorry for the mistake (but even so,
I learned
something already).

Thanks again,
Che
 
W

woooee

1. In this dict, if there is a UNIQUE max value, then its *key* is the
winner.
2. If there are any TIES for max value, then the *key* 'b' is the
winner by default.

This will store the max value(s) in a list. In case of a tie, you can
take the first value in the list, but it may be different than 'b'
since dictionary keys are in hash order, not in the order they were
entered. You can decide if you want the smallest key, or whatever
criterion is best.

the_dict = {'a':1, 'b':2, 'c':0, 'd':1, 'a0':2}
winners = [['*', -999]]
for key in the_dict:
max_value = winners[0][1] ## only lookup once
dict_value = the_dict[key] ## " " "
if dict_value > max_value:
winners = [[key, dict_value]]
elif dict_value == max_value:
winners.append([key, dict_value])

print winners
 
C

Chris Rebert

I realize, now though, (and Chris asked about this) that I was
imprecise in my
rules.  They really should be stated as:

1. In this dict, if there is a UNIQUE max value, then its *key* is the
winner.
2. If there are any TIES for max value, then the *key* 'b' is the
winner by default.

The point is, I am trying to determine the name of the winning
category, either
'a', 'b', or 'c', not the value of its winning score.

So in your solutions there is sorting by values, which makes sense.
But how
can I go back to keys from there?  Sorry for the mistake (but even so,
I learned
something already).

# still presumes at least 2 items
from heapq import nlargest
winner, runner_up = nlargest(2, the_dict, lambda k: the_dict[k])
if the_dict[winner] == the_dict[runner_up]:
winner = 'b'

Cheers,
Chris
 
T

Thomas Jollans

I have three items in a dict, like this:

the_dict = {'a':1, 'b':2, 'c':3}

but the vals could be anything. I want to configure something else
based on the "winner" of such a dict, with these rules:

1. In this dict, if there is a UNIQUE max value, that's the winner.
2. If there are any TIES for max value, b is the winner by default.

The problem for me, as I see it, is I don't know any elegant ways to
do this in Python. The max(dict) function doesn't distinguish between
unique and non-unique maxes. I could go through and test the various
possibilities (to see if the max value had any matches in the other
values), but, knowing Python, there is probably something close to
"one way to do it". Any suggestions?

# Untested.
def get_winner(adict):
values = sorted(adict.values(), reverse=True)
if values[0] == values[1]:
return adict['b']
else:
return values[0]

# Untested, with keys:
def get_winner(adict):
values = sorted(adict.items(), reverse=True,
key=(lambda k_v: k_v[1]))
if values[0][1] == values[1][1]:
return 'b'
else:
return values[0][0]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top