2010-09-02 19 views
8

Obs: Sé que las listas en python no están corregidas, pero creo que esta será. Y estoy usando Python 2.4Python: cómo hacer un pedido personalizado de una lista?

Tengo una lista, como (por ejemplo) éste:

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

se obtiene Esta milista variable de una función, y el 'orden' de la lista devuelta variará. Entonces, a veces será como en el ejemplo. A veces, el 'Informe' vendrá antes que 'Artículo', etc.

Tengo un orden fijo que quiero en esta lista (y no es el orden alfabético).

Digamos que mi orden fijo es: 'Informe', 'Artículo', 'libro', ...

Por lo tanto, lo que quiero es que: cualquiera que sea el orden 'milista' se crea una instancia, quiero reordenarlo haciendo que 'Informe' permanezca al frente, 'Artículo' en segundo lugar, etc ...

¿Cuál es el mejor enfoque para reordenar mi lista (tomando el primer elemento de la tupla de cada elemento en la lista) usando mi 'personalizada ' ¿orden?

respuesta:

terminé con esto:

milista se convirtió en una lista de dicts, así:

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

cada dict tener un 'id' que debía ser ordenado

guardar el orden correcto en un listAssigning la correct_order en una lista:

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

y haciendo:

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

Respuesta

13

Podría usar un diccionario que asignaría cada primer elemento a su "peso" y luego verificaría este diccionario dentro de una función de clasificación.

Algo así como:

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

Es mejor usar una función de tecla en lugar de la función cmp en desuso que ya no existe en Python 3: 'ordenó (mi lista, clave = lambda x: d [x [0]])' –

+0

No intenté con Python 3 todavía, entonces No sabía ... Gracias :) – Joril

+2

También se recomienda para Python 2, ya que usar una función clave es más rápido que una función cmp. Consulte http://docs.python.org/library/functions.html#sorted –

6

Se puede usar un diccionario, que permitiría acceder a "libro", "Artículo", etc. sin tener que preocuparse por el orden. Me volvería a poner los datos de dicha lista en un diccionario que se parecen a esto:

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

Si realmente desea ordenar la lista en la forma en que ha descrito, se puede utilizar el list.sort con una función clave que representa su particular, orden de clasificación (Documentation). Necesita la función clave ya que necesita acceder solo al primer elemento y su orden de clasificación tampoco es alfabético.

+2

http://wiki.python.org/moin/HowTo/Sorting/ de nuevo, este enlace es el más útil en esta pregunta! – dmitko

0

De esta manera se crea un diccionario y tira de los artículos de la misma con el fin

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] 

De esta manera utiliza especie con O (1) operaciones de búsqueda para el

ordenar
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

De manera más general, podría haber elementos de la lista secundaria que no están en el orden fijo especificado. Esto ordenará de acuerdo a la regla, pero deja en paz el orden relativo de todo lo que fuera de la regla:

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'] 
Cuestiones relacionadas