2010-10-23 10 views
25
alist = [(1,3),(2,5),(2,4),(7,5)] 

ho bisogno di ottenere il valore minimo e massimo per ogni posizione in tuple.Python: Trovare il min, valore massimo in una lista di tuple

Fox esempio: L'uscita exepected di alist è

min_x = 1 
max_x = 7 

min_y = 3 
max_y = 5 

Esiste un modo semplice per farlo?

+1

Quante volte si desidera iterare nella lista? (4 volte, 2 volte o 1 volte). – kennytm

risposta

59
map(max, zip(*alist)) 

Questa prima decomprime la vostra lista, poi trova il massimo per ogni posizione tupla

>>> alist = [(1,3),(2,5),(2,4),(7,5)] 
>>> zip(*alist) 
[(1, 2, 2, 7), (3, 5, 4, 5)] 
>>> map(max, zip(*alist)) 
[7, 5] 
>>> map(min, zip(*alist)) 
[1, 3] 

Questo funziona anche per le tuple di qualsiasi lunghezza in un elenco.

+1

Bella risposta, devo ancora imparare a usare zip così elegantemente in modo elegante – pyfunc

+1

puoi dire qualcosa in più su ciò che fa * di fronte a alist? zip si comporta DAVVERO diversamente senza * ci ... – Andrew

+5

@Andrew Certo, '*' unisce la lista agli argomenti della funzione. Il modo migliore per capire questo è con l'esempio: 'f (* [1, 2, 3])' è esattamente lo stesso di 'f (1, 2, 3)', quindi 'zip (* [(1, 3) , (2, 5), (2, 4), (7, 5)]) 'è uguale a' zip ((1, 3), (2, 5), (2, 4), (7, 5)) 'che restituisce' [(1, 2, 2, 7), (3, 5, 4, 5)] '. Per i dettagli completi, vedi la [documentazione] (http://docs.python.org/2/reference/expressions.html#calls) – cobbal

8
>>> from operator import itemgetter 
>>> alist = [(1,3),(2,5),(2,4),(7,5)] 
>>> min(alist)[0], max(alist)[0] 
(1, 7) 
>>> min(alist, key=itemgetter(1))[1], max(alist, key=itemgetter(1))[1] 
(3, 5) 
3

Un approccio generalizzato sarebbe qualcosa di simile a questo:

alist = [(1,6),(2,5),(2,4),(7,5)] 

temp = map(sorted, zip(*alist)) 
min_x, max_x, min_y, max_y = temp[0][0], temp[0][-1], temp[1][0], temp[1][-1] 

Per Python 3, avresti bisogno modificare la riga che crea temp a:

temp = tuple(map(sorted, zip(*alist))) 

L'idea può essere Estratto in una funzione che funziona sia in Python 2 che in 3:

from __future__ import print_function 
try: 
    from functools import reduce # moved into functools in release 2.6 
except ImportError: 
    pass 

# readable version 
def minmaxes(seq): 
    pairs = tuple() 
    for s in map(sorted, zip(*seq)): 
     pairs += (s[0], s[-1]) 
    return pairs 

# functional version 
def minmaxes(seq): 
    return reduce(tuple.__add__, ((s[0], s[-1]) for s in map(sorted, zip(*seq)))) 

alist = [(1,6), (2,5), (2,4), (7,5)] 
min_x, max_x, min_y, max_y = minmaxes(alist) 
print(' '.join(['{},{}']*2).format(*minmaxes(alist))) # 1,7 4,6 

triplets = [(1,6,6), (2,5,3), (2,4,9), (7,5,6)] 
min_x, max_x, min_y, max_y, min_z, max_z = minmaxes(triplets) 
print(' '.join(['{},{}']*3).format(*minmaxes(triplets))) # 1,7 4,6 3,9 
+0

Questa è una cattiva soluzione dal momento che l'ordinamento è 'O (n × log (n))' mentre il minimo è 'O (n)' – Grief

+0

@Grief: Per parafrasare un popolare linguaggio americano, la generalità non è libera. – martineau

+0

risposta @cobbal migliorata da @tiwo non è meno generale ma molto più semplice: 'lista (map (max, * [(1,9), (2,8), (3,7)]))' restituisce '[ 3, 9] 'così come la versione' min' restituire '[1, 7]' – Grief

3

Almeno con Python 2.7, il "zip" non è necessario, quindi questo semplifica a map(max, *data) (dove data è un iteratore su tuple o elenchi della stessa lunghezza).

+0

Non sei sicuro di cosa intendi, perché 'map (max, * alist)' è '[7, 6]' (com'è 'map (max, * iter (alist))'). – martineau

+0

@martineau 'map (max, * alist)' restituisce '[7, 5]', proprio come 'map (max, zip (* alist))' fa. – flornquake

+0

@flornquake: In realtà entrambi producono "[7, 6]" in Python 2.7. Il mio commento iniziale è stato perché non c'è nulla nella domanda iniziale sull'uso di 'zip', quindi non capisco la rilevanza di questa" risposta ".Forse è stato un commento sulla risposta di @ cobbal. Tuttavia, non si applica a mio che utilizza 'map (ordinato, zip (* alist))'. – martineau

0

Un'altra soluzione utilizzando enumerare e di lista

alist = [(1,3),(2,5),(2,4),(7,5)] 

for num, k in enumerate(['X', 'Y']): 
    print 'max_%s' %k, max([i[num] for i in alist]) 
    print 'min_%s' %k, min([i[num] for i in alist]) 
Problemi correlati