2015-08-03 25 views
8

Ho una lista che assomiglia a questo:Python Ordinamento personalizzato funzione per una lista

['Fall 2014', 'Spring 2015', 'Fall 2008', 'Spring 2008']

E quando ordinato, l'elenco dovrebbe essere simile a questo:

['Spring 2015', 'Fall 2014', 'Spring 2008', 'Fall 2008']

Quindi, le regole per l'ordinamento sono:

  1. F ordina per anno

  2. Ordina per stagione, dove la primavera è la prima, quindi l'autunno.

Al momento ho una funzione chiamata lcmp che uso nella mia lista come questa: myList.sort(lcmp).

>>> def lcmp(a,b): 
...  c = a.split() 
...  d = b.split() 
...  if(c[1]>d[1]): 
...    if(c[0]>d[0]): 
...      return 1 
...    else: 
...      return -1 
...  else: 
...    if(c[0]>d[0]): 
...      return 1 
...    else: 
...      return 0 
... 

Questo funziona per l'ordinamento per anno, ma non funziona per la stagione, anche se ho specificato che tipo di ordinamento. Perché sta succedendo?

risposta

5

Utilizzare semplicemente -year per invertire l'ordinamento per anno come prima chiave e il risultato di seas != "Spring" per rompere i legami utilizzando key=sort_function.

l = ['Fall 2014', 'Spring 2015', 'Fall 2008', 'Spring 2008'] 
def key(x): 
    seas,year = x.split() 
    return -int(year), seas != "Spring" 

l.sort(key=key) 

Non v'è alcun modo la funzione funzionerà anche se si utilizza myList.sort(key=lcmp) come si passa singole stringhe in modo da non avere a e b per dividere. Questo funziona anche per Python 2 o 3.

+0

O semplicemente sorta due volte utilizzando diverse funzioni chiave, che sembra essere raccomandato dal doc. Questo funziona perché 'sort()' è stabile ed è in grado di trarre vantaggio dalla quasi ordinanza. –

+0

Buono, e per 'mari' forse l'indice di un iterable contiene le stagioni! – Kasramvd

+0

@ Kasramvd, non sono sicuro che io segua? –

0

Si dovrebbe anche prendere in considerazione i casi in cui i valori confrontati sono uguali:

def lcmp(a,b): 
    c = a.split() 
    d = b.split() 
    if c[1] > d[1]: 
     return 1 
    elif c[1] == d[1]: 
     if c[0] > d[0]: 
      return -1 
     elif c[0] == d[0]: 
      return 0 
     else: 
      return 1 
    else: 
     return -1 

È quindi possibile ordinare i dati utilizzando myList.sort(lcmp) o myList.sort(cmp=lcmp)

2

Uno degli errori è che non si controlla correttamente l'uguaglianza. Cosa restituisci quando c[1] < d[1] e c[0] < d[0]? La risposta è zero, che non è corretto. Inoltre dovresti dichiarare l'argomento cmp in ordine. Che cosa si può fare è il seguente:

seasons = { 
    'Spring': 1, 
    'Summer': 2, 
    'Fall': 3, 
    'Winter': 4, 
} 
def lcmp(a, b): 
    a_season, a_year = a.split() 
    b_season, b_year = b.split() 
    return int(b_year) - int(a_year) or seasons[a_season] - seasons[b_season] 

l = ['Fall 2014', 'Spring 2015', 'Fall 2008', 'Spring 2008'] 
l.sort(cmp=lcmp) 

Risultato:

['Spring 2015', 'Fall 2014', 'Spring 2008', 'Fall 2008'] 

E se si vuole giocare con iteratori:

from itertools import ifilter, izip 

def lcmp(a, b): 
    it = (
     f(y) - f(x) 
     for x, y, f in izip(
      reversed(a.split()), 
      reversed(b.split()), 
      (int, lambda _: -seasons[_]) 
     ) 
    ) 
    return next(ifilter(None, it), 0) 
Problemi correlati