2017-10-18 4 views
1

J'ai une base de données avec des millions de dossiers comme celui-ci:Quelle est la meilleure façon d'inverser le tri d'une liste avec ce format de date?

[("Something", "10/08/2017", "something else", "something more", "etc"), 
("Something", "16/08/2017", "something else", "something more", "etc"), 
("Something", "14/07/2017", "something else", "something more", "etc"), 
("Something", "14/08/2017", "something else", "something more", "etc"), 
("Something", "15/07/2017", "something else", "something more", "etc"), 
("Something", "14/08/2017", "something else", "something more", "etc")] 

C'est JJ/MM/YYYY Et je besoin infirmée par la triées 2ème valeur.

Première tentative:
J'ai essayé, mais il ne trie que le jour, et non par mois.

def sort_by(my_list, index): 
    my_list.sort(key=lambda x: x[index], reverse=True) 
    return my_list 

Image du résultat (ignorer les couleurs, il est de mon GUI): https://image.prntscr.com/image/ZeIgzxNaQ2OD4VX0Yztnhw.png
Comme vous pouvez le voir trie seulement par jour, mais pas par mois, il ne cesse de sauter d'un mois à un autre chaque fois que le jour change. C'est un gâchis total.

Deuxième tentative:

def sort_by_date(my_list, index): 
    for record, data in enumerate(my_list): 
     split = data[index].split("/") 
     altered_record = my_list[record] 
     altered_record[index] = split[2]+"-"+split[1]+"-"+split[0] 
    my_list.sort(key=lambda x: x[index], reverse=True) 
    return my_list 

Et ce moment-là je l'ai réalisé ne fonctionnera pas parce que tuples ne permet pas l'attribution de l'article, donc je dois transformer l'ensemble des données dans une liste de listes au lieu d'une liste de tuples. Et même si je fais cela, je doute que ce soit efficace et qu'il faudra beaucoup de temps pour faire le travail.

Ma question est la suivante:
Comment voulez-vous trier une liste de tuples par JJ/MM/AAAA?

Comme par commentaire de @ juanpa.arrivillaga, la sortie désirée est une liste triée inversée par date:

31/12/2017 
30/12/2017 
29/12/2017 
28/12/2017 
(And the next days of that month) 
30/11/2017 
29/11/2017 
28/11/2017 
27/11/2017 
(And so go on) 

Edit: Si possible, je veux garder la date comme une chaîne, ne change pas la type de date.

+0

Pouvez-vous décrire * exactement * ce que vous cherchez (comme dans produire la sortie correspondante de votre exemple d'entrée)? –

+0

Aussi, vous dites que vous voulez garder la date comme une chaîne, et pourtant, vous voulez * le traiter comme une date ... pourquoi? –

+0

Sortie souhaitée ajoutée. Et je veux garder le résultat sous forme de chaîne pour l'afficher facilement sur mon interface graphique, car il est plus facile de montrer une chaîne que de la transformer à partir d'une date à chaque fois. Cela pourrait être un mouvement de noob car j'apprends encore Python. – Saelyth

Répondre

6

Vous pouvez utiliser le module datetime de Python pour cela:

from pprint import pprint 
from datetime import datetime 

database = [("Something", "10/08/2017", "something else", "something more", "etc"), 
      ("Something", "16/08/2017", "something else", "something more", "etc"), 
      ("Something", "14/07/2017", "something else", "something more", "etc"), 
      ("Something", "14/08/2017", "something else", "something more", "etc"), 
      ("Something", "15/07/2017", "something else", "something more", "etc"), 
      ("Something", "14/08/2017", "something else", "something more", "etc")] 

pprint(sorted(database, key=lambda x: datetime.strptime(x[1], "%d/%m/%Y"), reverse=True)) 

qui a sortie:

[('Something', '16/08/2017', 'something else', 'something more', 'etc'), 
('Something', '14/08/2017', 'something else', 'something more', 'etc'), 
('Something', '14/08/2017', 'something else', 'something more', 'etc'), 
('Something', '10/08/2017', 'something else', 'something more', 'etc'), 
('Something', '15/07/2017', 'something else', 'something more', 'etc'), 
('Something', '14/07/2017', 'something else', 'something more', 'etc')] 
+0

Testé, cela fonctionne. Je l'accepterai dès que possible. – Saelyth

1

En supposant que vous avez la base de données l'ensemble des dossiers 1M en mémoire, la meilleure solution serait:

sorted(my_list, key=lambda rec: int(rec[1][-4:] + rec[1][3:5] + rec[1][:2]), reverse=True) 

Il est très proche de votre deuxième solution, sauf que vous ne modifiez pas la liste du tout, mais extrayez simplement la clé de chaque enregistrement à la demande. Et la clé aura la forme 20170811 du type entier pour la chaîne '11/08/2017' d'origine.

Et il ne crée pas les objets datetime, car l'analyse peut être trop coûteuse, lorsque vous en avez besoin uniquement pour le tri.

Et il compare encore plus vite que les objets datetime et que les chaînes. Parce que la comparaison entière est la plus rapide possible.

Et il consomme le moins de mémoire pendant le tri, car les entiers sont la manière la plus compacte de stocker les clés (par rapport aux chaînes de caractères &).


Il peut être encore plus optimisé (sans bénéfice réel, mais pour le plaisir) en stockant le nombre de jours écoulés depuis une date de base (comparer: 20170811 (20'170'811) vs 736551 (736'551) depuis le 01.01.0001 ou 17389 (17'389) depuis le 01.01.1970). Et le coût de calcul n'est pas beaucoup plus grand, comparé à l'analyse de datetime.

sorted(my_list, key=lambda rec: int(rec[1][-4:])*32*12 + int(rec[1][3:5])*32 + int(rec[1][:2]), reverse=True) 

Ici, nous supposons que chaque mois est toujours 32 jours, et chaque année est toujours 32 * 12 = 384 jours. Parce que nous ne nous soucions pas du nombre réel de jours, mais seulement de leur position relative sur l'axe numérique. Cela couvre les cas avec 28-29-30-31 jours facilement.


PS: Cependant, si vous avez vraiment une base de données de dossiers 1M, je vous conseille de faire le tri dans le serveur de base de données avec SQL appropriée - plus rapide et plus optimisé. Mais c'est un autre grand sujet qui dépend de la façon dont la base de données est organisée.

+2

Il est vrai que l'analyse d'un objet 'datetime' est plus onéreuse, mais la comparaison d'objets' datetime' (ie '<', '>', etc.) est plus rapide que la comparaison de chaînes car il y a moins de travail à faire. Puisque la comparaison est effectuée plus que la transformation pendant le tri, cela peut valoir le coût initial de la conversion 'datetime' pour les très grands ensembles de données. – SethMMorton

+0

@SethMMorton Cela est vrai. Je viens de mettre à jour ma réponse pour convertir les ficelles en ints. Maintenant, il est encore plus rapide que les objets string et datetime, car quoi de plus rapide que la comparaison int? ;-) –