2009-11-05 9 views
9

He leído this post y no ha terminado trabajando para mí.Ordenar una lista multidimensional por un número variable de claves

Editar: la funcionalidad que estoy describiendo es igual que la función de clasificación en Excel ... si eso hace que sea más claro

Aquí está mi situación, tengo un documento de texto delimitado por tabuladores. Hay aproximadamente 125,000 líneas y 6 columnas por línea (las columnas están separadas por un carácter de tabulación). He dividido el documento en una lista de dos dimensiones.

Estoy tratando de escribir una función genérica para ordenar listas bidimensionales. Básicamente me gustaría tener una función donde pueda pasar la lista grande, y la clave de una o más columnas por las que me gustaría ordenar la lista grande. Obviamente, me gustaría que la primera clave pasara a ser el punto de clasificación principal, luego la segunda clave, etc.

¿Aún confunde?

Aquí hay un ejemplo de lo que me gustaría hacer.

Joel 18 Orange 1 
Anna 17 Blue 2 
Ryan 18 Green 3 
Luke 16 Blue 1 
Katy 13 Pink 5 
Tyler 22 Blue 6 
Bob  22 Blue 10 
Garrett 24 Red 7 
Ryan 18 Green 8 
Leland 18 Yellow 9 

Di pasé esta lista para mi función mágica, así:

sortByColumn(bigList, 0) 

Anna 17 Blue 2 
Bob  22 Blue 10 
Garrett 24 Red 7 
Joel 18 Orange 1 
Katy 13 Pink 5 
Leland 18 Yellow 9 
Luke 16 Blue 1 
Ryan 18 Green 3 
Ryan 18 Green 8 
Tyler 22 Blue 6 

y ...

sortByColumn(bigList, 2, 3) 

Luke 16 Blue 1 
Anna 17 Blue 2 
Tyler 22 Blue 6 
Bob  22 Blue 10 
Ryan 18 Green 3 
Ryan 18 Green 8 
Joel 18 Orange 1 
Katy 13 Pink 5 
Garrett 24 Red 7 
Leland 18 Yellow 9 

Alguna pista?

Respuesta

11
import operator: 
def sortByColumn(bigList, *args) 
    bigList.sort(key=operator.itemgetter(*args)) # sorts the list in place 
+0

Eso es fabuloso. Nunca había oído hablar de itemgetter (o attrgetter, que ahora también veo). –

+2

Esa es la máquina del tiempo de Guido para ti. http://catb.org/jargon/html/G/Guido.html –

+0

Esto es exactamente lo que estoy buscando. ¡Muchas gracias! –

8

Esto ordenará por las columnas 2 y 3:

a.sort(key=operator.itemgetter(2,3)) 
1

Asegúrese de que haya convertido los números de enteros, de lo contrario se ordenan alfabéticamente en lugar de numéricamente

# Sort the list in place 
def sortByColumn(A,*args): 
    import operator 
    A.sort(key=operator.itemgetter(*args)) 
    return A 

o

# Leave the original list alone and return a new sorted one 
def sortByColumn(A,*args): 
    import opertator 
    return sorted(A,key=operator.itemgetter(*args)) 
2

La idea clave aquí (juego de palabras intencionado) es usar una función clave que devuelve una tupla. A continuación, la función de la tecla es lambda x: (x[idx] for idx in args) x se establece para que sea igual a un elemento de una lista, es decir, una fila de datos. Devuelve una tupla de valores, no solo un valor. El método sort() ordena de acuerdo con el primer elemento de la lista, luego rompe relaciones con el segundo, y así sucesivamente. Ver http://wiki.python.org/moin/HowTo/Sorting#Sortingbykeys

#!/usr/bin/env python 
import csv 
def sortByColumn(aList,*args): 
    aList.sort(key=lambda x: (x[idx] for idx in args)) 
    return aList 

filename='file.txt' 
def convert_ints(astr): 
    try: 
     return int(astr) 
    except ValueError: 
     return astr  
biglist=[[convert_ints(elt) for elt in line] 
     for line in csv.reader(open(filename,'r'),delimiter='\t')] 

for row in sortByColumn(biglist,0): 
    print row 

for row in sortByColumn(biglist,2,3): 
    print row 
+1

Los números se deben convertir a ints –

+0

Buen punto, gnibbler. Fijo. – unutbu

Cuestiones relacionadas