Create function in python to find the highest of all function arguments, and return the “tag” of the value

StackOverflow https://stackoverflow.com/questions/4577345

  •  14-10-2019
  •  | 
  •  

Question

Consider the following: p1=1; p2=5; p3=7; highest=max(p1,p2,p3).

The max function would return 7. I am looking to create a similar function, which would return "p3". I have created a small function (by simple comparisons) for the above example, shown below. however I am having trouble when the number of arguments go up.

def highest(p1,p2,p3):
    if (p1>p2) and (p1>p3):
        return "p1"
    if (p2>p1) and (p2>p3):
        return "p2"
    if (p3>p1) and (p3>p1):
        return "p3"

Is there a simpler way to do this>

Was it helpful?

Solution

Update: Paul Hankin pointed out that max() took a key function, which I didn't know. So:

>>> def argmax(**kw):
...   return max(kw, key=kw.get)
... 
>>> argmax(foo=3, bar=5, frotz=1, kaka=-3)
'bar'

Other solutions for completeness:

In Python 2.7 and 3.x you can use dictionary comprehensions.

>>> def argmax(**kw):
...     wk = {v:k for k,v in kw.items()}
...     return wk[max(wk)]
... 
>>> argmax(foo=3, bar=5, frotz=1, kaka=-3)   
'bar'

Dictionary comprehensions are neat. :)

In earlier versions of Python you can do this:

>>> def argmax(**kw):
...     wk = dict([(v,k) for k,v in kw.items()])
...     return wk[max(wk)]
... 
>>> argmax(foo=3, bar=5, frotz=1, kaka=-3)   
'bar'

Which will work in anything after Python 2.2 or so.

OTHER TIPS

There is no way to get the name of the variable that had the highest value in the caller (because it might be a number or a complex expression), but by using keyword arguments exclusively, you can get the name of the parameter. Something like this:

def argmax(**kwargs):
    mx = -1e+400 # overflows to -Inf
    amx = None
    for k, v in kwargs.iteritems():
        if v > mx:
            mx = v
            amx = k
    return amx

Works like this:

>>> argmax(a=1,b=2,c=3)
'c'

but the catch is, it doesn't work if any of the arguments is positional:

>>> argmax(1,2,3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argmax() takes exactly 0 arguments (3 given)

Depending on what you're doing, this construct might be more useful: (hat tip to http://lemire.me/blog/archives/2008/12/17/fast-argmax-in-python/ )

>>> a = [9,99,999]
>>> a.index(max(a))
2

The only way to keep this anything close to extensible is to take a list as argument and return the index of its highest element. You can put a p in front and begin counting at 1 if you really want to.

def highest(x):
    return 'p' + repr(x.index(max(x))+1)

Obviously it dose not handle variable length arguments. If you want variable length argument then that's a different issue. If you have 10 arguments then just add them in the definition and it will return the correct argument name (not necessarily started with 'p'). But the catch is the number of arguments (3 or 5 or 10 or whatever else) is not variable. You need to know how many arguments you require.

def highest(p1,p2,p3,p4,p5):
    d = locals()
    keys = d.keys()
    max_key = keys[0]
    max_val = d[max_key]
    for i in range(1,len(keys)):
        key = keys[i]
        val = d[key]
        if val > max_val:
            max_val = val
            max_key = key

    return max_key

print highest(3,2,5,10,1)
print highest(1,5,2,2,3)
print highest(5,2,5,1,11)
print highest(3,2,1,1,2)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top