Crea una funzione in Python per trovare il più alto di tutti gli argomenti delle funzioni, e restituire il “tag” del valore
Domanda
Si consideri il seguente: p1 = 1; p2 = 5; p3 = 7; più alto = max (p1, p2, p3).
La funzione di massima sarebbe tornato 7. Sto cercando di creare una funzione simile, che sarebbe tornato "P3". Ho creato una piccola funzione (da semplici confronti) per l'esempio precedente, mostrato di seguito. tuttavia Ho problemi quando il numero di argomenti salire.
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"
C'è un modo più semplice per fare questo>
Soluzione
Aggiornamento: Paul Hankin ha sottolineato che max () ha preso una funzione chiave, che non conoscevo. Quindi:
>>> def argmax(**kw):
... return max(kw, key=kw.get)
...
>>> argmax(foo=3, bar=5, frotz=1, kaka=-3)
'bar'
Altre soluzioni per la completezza:
In Python 2.7 e 3.x è possibile utilizzare il dizionario comprensioni.
>>> 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'
comprensioni dizionario sono pulite. :)
Nelle versioni precedenti di Python si può fare questo:
>>> 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'
che lavorerà nel nulla dopo Python 2.2 o giù di lì.
Altri suggerimenti
Non v'è alcun modo per ottenere il nome del variabile che ha avuto il più alto valore del chiamante (perché potrebbe essere un numero o un'espressione complessa), ma utilizzando esclusivamente argomenti a parola chiave, è possibile ottenere il nome del il parametro . Qualcosa di simile a questo:
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
funziona in questo modo:
>>> argmax(a=1,b=2,c=3)
'c'
, ma il problema è, non funziona se uno degli argomenti è posizionale:
>>> argmax(1,2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argmax() takes exactly 0 arguments (3 given)
A seconda di quello che stai facendo, questo costrutto potrebbe essere più utile: (Punta di cappello a http://lemire.me/blog/archives/2008/12/17/fast-argmax-in-python/ )
>>> a = [9,99,999]
>>> a.index(max(a))
2
L'unico modo per mantenere questo nulla vicino a estendibile è quello di prendere una lista come argomento e restituire l'indice del suo elemento più alto. Si può mettere un p di fronte e iniziare il conteggio a 1 se si vuole veramente.
def highest(x):
return 'p' + repr(x.index(max(x))+1)
Ovviamente dose non gestire argomenti di lunghezza variabile. Se si desidera che l'argomento lunghezza variabile allora questo è un problema diverso. Se si dispone di 10 argomenti poi basta aggiungerli nella definizione e restituirà il nome di argomento corretto (non necessariamente iniziare con 'p'). Ma il problema è il numero di argomenti (3 o 5 o 10 o qualsiasi altra cosa) non è variabile. Hai bisogno di sapere quanti argomenti si richiedono.
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)