2012-10-25 8 views
19

Ho questa lista di oggetti che hanno un parametro x ed un y (e alcune altre cose).Python: Ottenere il valore massimo di y da un elenco di oggetti

path.nodes = (
    <GSNode x=535.0 y=0.0 GSLINE GSSHARP>, 
    <GSNode x=634.0 y=0.0 GSLINE GSSHARP>, 
    <GSNode x=377.0 y=706.0 GSLINE GSSHARP>, 
    <GSNode x=279.0 y=706.0 GSLINE GSSHARP>, 
    <GSNode x=10.0 y=0.0 GSLINE GSSHARP>, 
    <GSNode x=110.0 y=0.0 GSLINE GSSHARP>, 
    <GSNode x=189.0 y=216.0 GSLINE GSSHARP>, 
    <GSNode x=458.0 y=216.0 GSLINE GSSHARP> 
) 

Ho bisogno di avere il massimo di questa lista. Anche se, ho provato questo:

print max(path.nodes, key=y) 

E ottengo questo errore:

NameError: name 'y' is not defined 

Sono genere di nuovo al pitone e il doc dà la mia idea. Penso che sto facendo male con la parola chiave, perché se scorrere i nodi come questo:

for node in path.nodes: 
    print node.y 

Prendo i valori di y. Qualcuno potrebbe fornirmi una spiegazione?

+0

Wow! Grazie ragazzi! È stato veloce e mi fornisce gli indizi di cui avevo bisogno! – PDXIII

+1

@Wtower Grazie per la modifica. Ora è molto più leggibile! – PDXIII

risposta

36

per ottenere solo il valore massimo e non l'intero oggetto è possibile utilizzare un generatore di espressione:

print max(node.y for node in path.nodes) 
+2

Avrei scelto il metodo 'key = lambda x: x.y', proprio come gli altri. Ma ** questo ** è ciò che puoi veramente chiamare * pythonic *! +1 –

+1

Questo è esattamente quello che stavo cercando. Sintassi pazzesca! Mi piace! – PDXIII

14

C'è un built-in per aiutare con questo caso.

import operator 

print max(path.nodes, key=operator.attrgetter('y')) 

alternativa:

print max(path.nodes, key=lambda item: item.y) 

Edit: Ma la risposta di Mark Byers' è più Pythonic.

print max(node.y for node in path.nodes) 
+1

Nel mio caso il modo più pisano è quello che stavo cercando.Ma negli altri esempi c'è un vantaggio del attrgetter() rispetto allo stile lambda? – PDXIII

1
from operator import attrgetter 
print max(path.nodes, key=attrgetter("y")) 
+1

Questo va bene se ho bisogno dell'oggetto. Grazie! – PDXIII

0

y non è definito come variabile; è un attributo di singoli oggetti GSNode; non puoi usarlo come nome a parte.

Per accedere ai singoli attributi è possibile utilizzare qualcosa come key=lambda x: x.y o attrgetter() dal modulo operator.

+0

Grazie per la spiegazione! Sta diventando più luminoso! – PDXIII

2

C'è una differenza importante per quando usare lo stile "Pythonic" # 1 contro stile lambda # 2:

max(node.y for node in path.nodes) (style #1) 

contro

max(path.nodes, key=lambda item: item.y) (style #2) 

Se si guarda attentamente si può vedere che lo stile # 1 restituisce il valore massimo per l'attributo "y" mentre lo stile # 2 restituisce il "nodo" che ha l'attributo massimo "y". Questi due non sono gli stessi e l'utilizzo del codice è importante nel caso in cui si desideri eseguire un'iterazione sui valori degli attributi o iterare sugli oggetti che contengono tale attributo.

Esempio:

class node(): 
    def __init__(self,x): 
     self.x = x 
     self.y = self.x + 10 

node_lst = [node(1),node(2),node(3),node(4), node(5)] 
print ([(e.x,e.y) for e in node_lst]) 

>>> [(1, 11), (2, 12), (3, 13), (4, 14), (5, 15)] 

Ora:

maxy = max(node.y for node in node_lst) 
print(maxy) 
>>> 15 

max_node = max(node_lst, key=lambda node: node.y) 
print(max_node.y) 
>>> 15 
Problemi correlati