Cómo ordenar las columnas de una lista en Python

CorePress2024-01-25  289

Hay una lista como

List = [['19-03-2006', 10000 ], 
    ['02-09-2006', 68 ], 
    ['03-07-2006', 300 ], 
    ['03-07-2006', 80 ], 
    ['03-07-2006', 200 ], 
    ['03-07-2006', 30 ]]

Intenta generar resultados como:

List =  [['19-03-2006', 30 ]] 
         ['19-03-2006', 10000 ], 
         ['03-07-2006', 300 ],
         ['02-09-2006', 68 ], 
         ['02-09-2006', 80 ],   
         ['15-10-2006', 200 ]]

Primero ordene por fecha, de más antigua a más reciente, y luego por número, de menor a mayor. ¿Cómo puedo hacer esto sin utilizar módulos como datetime?

corrija su entrada para usar delimitadores de cadena adecuados

-miquelvir

28 de marzo de 2021 a las 9:44

acepta mi sugerencia de edición para corregir la entrada

-miquelvir

28 de marzo de 2021 a las 9:46

Lo siento, ya está arreglado

-nd87h7823gd

28 de marzo de 2021 a las 9:47

¿Por qué '03-07-2006' después de '02-09-2006'?

-Manuel

28 de marzo de 2021 a las 9:48

¿De dónde viene ['19-03-2006', 30 ]? Eso no está en tu opinión. Y la salida no es válida debido a ese temprano ]].

-Manuel

28/03/2021 a las 10:02



------------------------------------

Puedes utilizar el viejo comparador convertido a función clave. Desde Python 3.2, la función functools.cmp_to_key() se ha agregado a la biblioteca estándar

from functools import cmp_to_key

def comparator(a, b):
    a_date, a_num = a
    b_date, b_num = b
    
    a_date = tuple(map(int, reversed(a_date.split("-"))))
    b_date = tuple(map(int, reversed(b_date.split("-"))))
    
    # By year
    if a_date[0] > b_date[0]:
        return 1
    elif a_date[0] < b_date[0]:
        return -1
    else:
        # By month
        if a_date[1] > b_date[1]:
            return 1
        elif a_date[1] < b_date[1]:
            return -1
        else:
            # By day
            if a_date[2] > b_date[2]:
                return 1
            elif a_date[2] < b_date[2]:
                return -1
            else:
                # By number
                if a_num > b_num:
                    return 1
                elif a_num < b_num:
                    return -1
                else:
                    return 0

data = [
    ['19-03-2006', 10000], 
    ['02-09-2006', 68], 
    ['03-07-2006', 300], 
    ['03-07-2006', 80], 
    ['03-07-2006', 200], 
    ['03-07-2006', 30]
]

sorted(data, key=cmp_to_key(comparator))

Salida:

[['19-03-2006', 10000],
 ['03-07-2006', 30],
 ['03-07-2006', 80],
 ['03-07-2006', 200],
 ['03-07-2006', 300],
 ['02-09-2006', 68]]



------------------------------------

Puede ordenar por la primera entrada en la sublista simplemente especificando sorted(lst, key=lambda x: x[0]). Por supuesto, también tendría que escribir una función para comparar dos marcas de fecha si no desea utilizar funciones existentes (como datetime y timedelta) para hacer esto.

Si desea ordenar primero con un método y luego con otro, puede simplemente proporcionar una tupla como clave, donde el primer elemento sea su orden principal.

------------------------------

Lo primero, utilice nombres significativos para las variables

Puede usar una clave ordenada y personalizada que sea el primer valor de cada matriz con el formato adecuado de fecha y hora. Sorted se encargará de ordenar.

import datetime

orders = [['19-03-2006', 10000],
      ['02-09-2006', 68],
      ['03-07-2006', 300],
      ['03-07-2006', 80],
      ['03-07-2006', 200],
      ['03-07-2006', 30]]

print(sorted(orders, key=lambda x: datetime.datetime.strptime(x[0], '%d-%m-%Y')))

Si desea una clasificación secundaria utilizando el valor, páselo también.

import datetime
orders = [['19-03-2006', 10000 ],
        ['02-09-2006', 68 ],
        ['03-07-2006', 300 ],
        ['03-07-2006', 80 ],
        ['03-07-2006', 200 ],
        ['03-07-2006', 30 ]]

print(sorted(orders, key=lambda x: (datetime.datetime.strptime(x[0], '%d-%m-%Y'), x[1])))

Sin usar fecha y hora, podemos simplemente pasar la fecha a un número entero y usarlo.

orders = [['19-03-2006', 10000 ],
        ['02-09-2006', 68 ],
        ['03-07-2006', 300 ],
        ['03-07-2006', 80 ],
        ['03-07-2006', 200 ],
        ['03-07-2006', 30 ]]


def date_to_integer(date):
    day, month, year = map(int, date.split('-'))
    return 10000*year + 100*month + day


print(sorted(orders, key=lambda x: (date_to_integer(x[0]), x[1])))

4

2

Esto no parece encajar en "¿Cómo puedo hacer esto sin utilizar módulos como datetime?"; pregunta.

-Manuel

28 de marzo de 2021 a las 9:52

¿Qué pasa si no uso fecha y hora? mi profesor no me permite usar este módulo, jajaja

-nd87h7823gd

28 de marzo de 2021 a las 9:54

2

Si tu profesor no quiere que uses un módulo, probablemente tampoco quiera que pidas a otros que resuelvan este problema por ti.

-ades

28 de marzo de 2021 a las 9:56

editado! pero lea meta.stackoverflow.com/questions/334822/…

-miquelvir

28 de marzo de 2021 a las 9:56



------------------------------------

No soy realmente un experto en Python, pero resumiría las cadenas de fechas antes de convertirlas en números enteros.

my_list = [
    ['19-03-2006', 10000],  
    ['02-09-2006', 68],    
    ['03-07-2006', 300],   
    ['03-07-2006', 80],     
    ['03-07-2006', 200],   
    ['03-07-2006', 30]     
]

def date_to_int(date):
    day, month, year = date.split('-')
    return int(year + month + day)

print(sorted(my_list, key = lambda x: (date_to_int(x[0]), x[1])))

Resultado:

[
    ['19-03-2006', 10000], # 20060319 10000
    ['03-07-2006', 30],    # 20060703 30
    ['03-07-2006', 80],    # 20060703 80
    ['03-07-2006', 200],   # 20060703 200
    ['03-07-2006', 300],   # 20060703 300
    ['02-09-2006', 68]     # 20060902 68
]
Respondido

28 de marzo de 2021 a las 11:16

Nick

Nick

1

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare