2010-09-02 14 views
8

Obs: so che gli elenchi in python non sono corretti per l'ordine, ma pensate che questo sarà. e sto usando Python 2.4Python: come ordinare un elenco personalizzato?

Ho un elenco, come (per esempio) questo:

mylist = [ (u'Article', {"...some_data..."} ) , 
      (u'Report' , {"...some_data..."} ) , 
      (u'Book' , {"...another_data..."}) , 
...#continue 
] 

Questa mylist variabile è ottenuto da una funzione, e l' 'ordine' della lista restituita varierà. Quindi, a volte sarà come nell'esempio. A volte, il "Rapporto" verrà prima di "Articolo", ecc.

Ho un ordine fisso che desidero in questo elenco (e non è l'alfabetico).

Diciamo che il mio ordine fisso è: 'Report', 'articolo', 'Book', ...

Quindi, quello che voglio è che: qualunque ordine 'mylist' viene creata un'istanza, voglio riordinare facendo 'Report' rimanere in primo piano, 'Articolo' al secondo, ecc ...

Qual è l'approccio migliore per riordinare la mia lista (prendendo il primo elemento della tupla di ogni elemento della lista) usando la mia 'custom' ' ordine?

Risposta:

ho finito con questo:

mylist divenne un elenco di dicts, in questo modo:

mylist = [{'id':'Article', "...some_data..."} , 
     ...etc 
] 

ogni dict avere un 'id' che doveva essere ordinato.

Salvare l'ordine corretto un listAssigning il correct_order in un elenco:

correct_order = ['Report', 'Article', 'Book', ...] 

e fare:

results = sorted([item for item in results], cmp=lambda x,y:cmp(correct_order.index(x['id']), correct_order.index(y['id']))) 

risposta

13

È possibile utilizzare un dizionario che dovrebbe mappare ogni primo elemento al suo "peso" e quindi controllare questo dizionario all'interno di una funzione di ordinamento.

Qualcosa di simile:

d = { "Report": 1, 
     "Article": 2, 
     "Book": 3 } 
result = sorted(mylist, key=lambda x:d[x[0]]) 
+10

Meglio usare una funzione chiave piuttosto che la funzione cmp deprecata che non esce più in Python 3: 'sort (mylist, key = lambda x: d [x [0]])' –

+0

Non ho ancora provato Python 3, quindi Non sapevo .. Grazie :) – Joril

+2

Si consiglia anche per Python 2 come l'utilizzo di una funzione chiave è più veloce di una funzione cmp. Vedi http://docs.python.org/library/functions.html#sorted –

6

si potrebbe usare un dizionario, che permetterebbe di accedere a "Libro", "Articolo", ecc. Senza doversi preoccupare dell'ordine. Io metterei i dati da tale lista in un dict che assomigliano a questo:

mydict = { u'Article': "somedata", 
      u'Report': "someotherdata", ...} 

Se davvero si vuole ordinare l'elenco nel modo descritto, è possibile utilizzare il list.sort con una funzione chiave che rappresenta la vostra particolare criterio di ordinamento (Documentation). È necessaria la funzione chiave in quanto è necessario accedere solo al primo elemento e il tuo ordine non è alfabetico.

+2

http://wiki.python.org/moin/HowTo/Sorting/ di nuovo, questo link è la più utile in questa domanda! – dmitko

0

In questo modo crea un dict e tira le voci da esso al fine

mylist = [ (u'Article', {"...some_data..."} ) , 
      (u'Report' , {"...some_data..."} ) , 
      (u'Book' , {"...another_data..."}) , 
] 

mydict = dict(mylist) 
ordering = [u'Report', u'Article', u'Book'] 

print [(k,mydict[k]) for k in ordering] 

In questo modo utilizza sorta con O (1) le ricerche per l'ordinamento

mylist = [ (u'Article', {"...some_data..."} ) , 
      (u'Report' , {"...some_data..."} ) , 
      (u'Book' , {"...another_data..."}) , 
] 

mydict = dict(mylist) 
ordering = dict((k,v) for v,k in enumerate([u'Report', u'Article', u'Book'])) 

print sorted(mydict.items(), key=lambda (k,v): ordering[k]) 
1

Più in generale, potrebbero esserci degli elementi della lista che non sono nell'ordine specificato specificato. Questo ordine in base alla regola, ma lasciare da solo l'ordine relativo di tutto al di fuori della norma:

def orderListByRule(alist,orderRule,listKeys=None,dropIfKey=None): 
    ### 
    ####################################################################################### 
    """ Reorder alist according to the order specified in orderRule. The orderRule lists the order to be imposed on a set of keys. The keys are alist, if listkeys==None, or listkeys otherwise. That is, the length of listkeys must be the same as of alist. That is, listkeys are the tags on alist which determine the ordering. orderRule is a list of those same keys and maybe more which specifies the desired ordering. 
    There is an optional dropIfKey which lists keys of items that should be dropped outright. 
    """ 
    maxOR = len(orderRule) 
    orDict = dict(zip(orderRule, range(maxOR))) 
    alDict = dict(zip(range(maxOR, maxOR+len(alist)), 
         zip(alist if listKeys is None else listKeys, alist))) 
    outpairs = sorted( [[orDict.get(b[0],a),(b)] for a,b in alDict.items()] ) 
    if dropIfKey is None: dropIfKey=[] 
    outL = [b[1] for a,b in outpairs if b[0] not in dropIfKey] 
    return outL 

def test_orderListByRule(): 
    L1 = [1,2,3,3,5] 
    L2 = [3,4,5,10] 
    assert orderListByRule(L1, L2) == [3, 3, 5, 1, 2] 
    assert orderListByRule(L1, L2, dropIfKey=[2,3]) == [5, 1,] 
    Lv = [c for c in 'abcce'] 
    assert orderListByRule(Lv, L2, listKeys=L1) == ['c', 'c', 'e', 'a', 'b'] 
    assert orderListByRule(Lv, L2, listKeys=L1, dropIfKey=[2,3]) == ['e','a'] 
Problemi correlati