Aller au contenu

Trier une liste de dates


fabcad

Messages recommandés

Bonjour Amis lispeurs,

 

Soit des listes de dates sous la forme :

 

list_dates_debut = ("31/12/2012" "28/10/2011" "01/03/2010" "25/04/2009"))

 

list_dates_fin = ("30/11/2015" "21/08/2013" "01/04/2012" "26/05/2009"))

 

1- Comment trier ces 2 listes.

2- Comment trouver le max et le min sur ces listes de dates.

 

Merci pour votre aide.

 

Fabcad

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

Ma première idée serait de convertir chaque date en un nombre entier (nombre de jours écoulés depuis le 01/01/0000 par exemple) pour faciliter le tri, puis de reconvertir en date ensuite.

Quitte à tricher pour simplifier, en considérant que toutes les années comptent 372 jours, et tous les mois comptent 31 jours...

Par exemple le 31/12/2012 deviendrait 31+11*31+2011*372 = 748464, et ainsi de suite. :unsure:

 

Edit: si tous les mois ont 31 jours, alors une année en compte 372... :rolleyes:

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Pas trop difficile avec la foison de routines laissé par (gile) sur le forum:

(defun tridates	(lst)
 (mapcar '(lambda (x) (lst2str (reverse x) "/"))
  (vl-sort (mapcar '(lambda (x) (reverse (str2lst x "/"))) lst)
	   'compareList
  )
 )
)

 

Avec les routines associées suivantes :

;; STR2LST
;; Transforme un chaine avec séparateur en liste de chaines
;;
;; Arguments
;; str : la chaine à transformer en liste
;; sep : le séparateur

;;
;; Exemples
;; (str2lst "a b c" " ") -> ("a" "b" "c")
;; (str2lst "1,2,3" ",") -> ("1" "2" "3")
;; (mapcar 'read (str2lst "1,2,3" ",")) -> (1 2 3)
(defun str2lst (str sep / pos)
 (if (setq pos (vl-string-search sep str))
   (cons (substr str 1 pos)
  (str2lst (substr str (+ (strlen sep) pos 1)) sep)
   )
   (list str)
 )
)

;; LST2STR
;; Concatène une liste et un séparateur en une chaine
;;
;; Arguments
;; lst : la liste à transformer en chaine
;; sep : le séparateur
;;
;; Exemples
;; (lst2str '(1 2 3) ",") -> "1,2,3"
;; (lst2str '("a" "b" "c") " ") -> "a b c"
(defun lst2str (lst sep)
 (if (cadr lst)
   (strcat (vl-princ-to-string (car lst))
    sep
    (lst2str (cdr lst) sep)
   )
   (vl-princ-to-string (car lst))
 )
)

;; Compare des listes par la tête
;; http://cadxp.com/index.php?/topic/29470-trier-une-liste/page__p__160087#entry160087
(defun compareList (l1 l2)
 (if (and (and l1 l2) (= (car l1) (car l2)))
   (compareList (cdr l1) (cdr l2))
   (< (car l1) (car l2))
 )
)

 

 

Donc pour avoir :

1- Comment trier cs 2 listes.

_$ (setq list_dates_debut (tridates '("31/12/2012" "28/10/2011" "01/03/2010" "25/04/2009")))
("25/04/2009" "01/03/2010" "28/10/2011" "31/12/2012")
$ (setq list_dates_fin (tridates '("30/11/2015" "21/08/2013" "01/04/2012" "26/05/2009")))
("26/05/2009" "01/04/2012" "21/08/2013" "30/11/2015")

 

2- Comment trouver le max et le min sur ces listes de dates.

 _$ (car list_dates_debut);retourne le min
"25/04/2009"
_$ (car list_dates_fin);retourne le min
"26/05/2009"
_$ (last list_dates_debut);retourne le max
"31/12/2012"
_$ (last list_dates_fin);retourne le max
"30/11/2015"

 

A+

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Dans le même esprit que VDH_Bruno, mais qui ne fonctionnera qu'avec des dates formatées : JJ/MM/AAAA.

 

(defun sortDate (lst)
 (vl-sort
   lst
   '(lambda (d1 d2)
      (if (= (substr d1 7) (substr d2 7))
        (if (= (substr d1 4 2) (substr d2 4 2))
          (< (substr d1 1 2) (substr d2 1 2))
          (< (substr d1 4 2) (substr d2 4 2))
        )
        (< (substr d1 7) (substr d2 7))
      )
    )
 )
)

 

on peut aussi définir une fonction de tri par clé (ici sortBy) qui accepte deux arguments : une fonction qui génère une clé pour chaque élément de la liste et la liste à trier.

Pour les dates formatées telles que ci-dessus, la fonction génèrera une clé AAAAMMJJ

 

(defun sortBy (fun lst)
 (setq fun (eval fun))
 (vl-sort lst '(lambda (x1 x2) (< (fun x1) (fun x2))))
)

(defun sortDate (lst)
 (sortBy '(lambda (s) (strcat (substr s 7) (substr s 4 2) (substr s 1 2))) lst)
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Dans la mêmme veine que la dernière, pour obtenir le minimum ou le maximum sans trier la liste (on ne la parcourt qu'une seule fois).

 

La fonction reduce applique la fonction spécifiée aux deux premiers éléments de la liste. Elle passe ensuite ce résultat dans la fonction avec le troisième élément et ainsi de suite. Enfin, elle retourne le résultat final. Si la fonction d'entrée est 'fun et que les éléments sont (i0...in), alors cette fonction calcule : (fun (... (fun (fun i0 i1) i2) ...) in).

 

Les fonctions minBy et maxBy appellent reduce en comparant les clés générées pour chaque élément de la liste.

 

(defun reduce (fun lst)
 (if (cdr lst)
   (reduce fun (cons ((eval fun) (car lst) (cadr lst)) (cddr lst)))
   (car lst)
 )
)

(defun minBy (fun lst)
 (reduce '(lambda (x y) (if (< ((eval fun) y) ((eval fun) x)) y x )) lst)
)

(defun maxBy (fun lst)
 (reduce '(lambda (x y) (if (> ((eval fun) y) ((eval fun) x)) y x )) lst)
)

 

(minBy '(lambda (s) (strcat (substr s 7) (substr s 4 2) (substr s 1 2))) list_dates_debut) retourne la date la pus ancienne, maxBy avec la même expression lambda, la date la plus récente.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Merci (gile), c’est très intéressant comme façon de faire :) :) :)

 

Juste une petite suggestion sur la forme, il me semble qu'en ne quotant pas la fonction lambda passé en argument à la fonction sortBy, on doit pouvoir économiser l'expression (setq fun (eval fun)) qui fait un peu symétrique, mais a sans doute le mérite d'être plus conventionnel:

(defun sortBy (fun lst)  
 (vl-sort lst '(lambda (x1 x2) (< (fun x1) (fun x2))))
)
(defun sortDate	(lst)
 (sortBy (lambda (s)
     (strcat (substr s 7) (substr s 4 2) (substr s 1 2))
   )
  lst
 )
)

 

 

----------- Edit ----------------

En voulant tester, pour minBy & maxBy j'ai le message d'erreur suivant:

; erreur: nombre d'arguments insuffisants

_$

Si j'ai un peu de temps en soirée j'essayerai de regarder plus dans le détail..

 

A+

Modifié par VDH-Bruno

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

J'ai préféré utiliser une fonction "quotée" comme argument pour respecter la syntaxe utilisée par les fonctions LISP natives (mapcar, vl-sort, etc.)

 

L'erreur est due au fait que j'ai utilisé le même symbole (fun) pour les fonctions passées en argument à reduce et minBy/maxBy

 

Utiliser plutôt celles-ci :

(defun sortBy (keygen lst)
 (setq keygen (eval keygen))
 (vl-sort lst '(lambda (x1 x2) (< (keygen x1) (keygen x2))))
)

(defun reduce (aggregate lst)
 (if (cdr lst)
   (reduce aggregate (cons ((eval aggregate) (car lst) (cadr lst)) (cddr lst)))
   (car lst)
 )
)

(defun minBy (keygen lst)
 (reduce '(lambda (x y) (if (< ((eval keygen) y) ((eval keygen) x)) y x )) lst)
)

(defun maxBy (keygen lst)
 (reduce '(lambda (x y) (if (> ((eval keygen) y) ((eval keygen) x)) y x )) lst)
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Merci pour la correction, je pensais jeter un œil dessus (en ce moment je suis amateur de cette façon de coder)et finalement j’en suis resté à méditer sur l’intérêt de transmettre en argument des fonctions «quoté», ce que je prenais à tord pour une convention (ou un simple respect de la syntaxe utilisée par les fonctions LISP natives) va un peu plus loin, faut jusque je réussisse à formuler cela de façon claire avant d’en faire un petit topo..

A+

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

Salut

 

Une autre méthode est de transformer la date au format julien. Après, c'est de la rigolade avec les fonctions min et max.

Ci-joint un vieux lisp (que je connais depuis la version 10 au moins) qui permet la convertion du calendrier julien au calendrier grégorien et inversement (peut-être aussi utile pour ceux qui travaille avec Excel).

 

@+

julian.lsp

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité