VL - Listes

 

Fonctions portant sur les listes
(list)

Cliquez le nom de la fonction
pour un accès direct dans la page ...

 

FONCTION MÉMENTO
vl-consp Vérifier si c'est une liste (list) ou pas
vl-list* Construire une liste (list)
vl-member-if Test dans une liste (list)
(par prédicat)
vl-member-if-not Recherche dans une liste (list)
(par prédicat) bis
vl-position Trouver la position d'un élément dans une liste (list)
vl-list-length Trouver la longueur d'une liste (list)
vl-remove Retirer un élément d'une liste (list)
vl-remove-if Retirer un élément d'une liste (list) avec test
vl-remove-if-not  Retirer un élément d'une liste (list) avec test bis
 vl-some  Tester un "prédicat" sur une combinaison d'éléments
vl-sort  Trier les éléments d'une liste (list)
vl-sort-i Trier "par index" les éléments d'une liste (list)
vl-every Vérifier un "prédicat"pour chaque combinaison d'éléments

 

Haut de page Retour menu Fonctions VL

 


vl-consp

Vérifier si c'est une liste (list) ou pas

 

Comme pour la fonction (listp) cette fonction VL va vérifier si l'élément passé en argument est une liste (list) ou pas.

Syntaxe : (vl-consp ListeArgument)
Cette fonction n'accepte qu'un seul argument ListeArgument qui peut être de type :
-  Nombre entier (integer),
-  Nombre réel (real),
-  Chaîne de caractères (string),
-  Liste (list),
-  Sous-routine (subroutine),
-  Nom d'entité (ename),
T, nil, ou (catch-all-apply-error ).

Valeur renvoyée :
- T si l'argument est une liste (list)
- nil si l'argument n'est pas une liste (list) ou une liste vide

 


Exemples :

(vl-consp '( 1 2 3))

Renvoie T

(vl-consp '( 1 2 3) '( 5 6 7))

Renvoie une erreur
erreur: nombre d'arguments trop important
à cause des deux arguments car un seul est autorisé.

(vl-consp '(( 1 2 3) ( 5 6 7)))

Renvoie T car la liste est unique bien qu'elle contienne plusieurs éléments

 (vl-consp "je suis une liste")

Renvoie nil car l'argument est une chaîne de caractères (string).

(vl-consp (cons 8 "NouveauCalque"))

Renvoie T, utilisation d'un symbol en argument.

(vl-consp nil)

Renvoie : nil (liste vide)

 

 

Haut de page Retour menu Fonctions VL

 

vl-list*

Construire une liste

Cette fonction va construire une liste avec les éléments donnés en arguments

Syntaxe : (vl-list* item [item ...])

Les arguments item peuvent être de type :
- Nombre entier (integer),
- Nombre réel (real),
- Chaîne de caractères (string),
- Liste (list),
File,
- Symbol,
- Nom d'entité (ename),
- T ou nil .

Valeur renvoyée :
Si le dernier argument est une liste (list) les éléments de cette liste sont ajoutés à l'ensemble des arguments précédents dans la liste construite.

Les valeurs possibles sont :
-- un atome (atom) si un simple atome (atom) est passé en argument
-- une paire pointée (dotted pair) si tous les éléments passés en arguments sont des atomes (atom).
-- une liste pointée (dotted list) si le dernier argument est un atome (atom) et qu'aucune des conditions précédentes n'est vraie.
-- une liste(list) si aucune des affirmations précédentes n'est vraie.

Exemples :

(vl-list* 10)

Renvoie : 10

(vl-list* 8 "nom_de_calque")

Renvoie : (8 . "nom_de_calque"),
J'ai pris cet exemple à dessein pour fabriquer une paire pointée (dotted pair) de code DXF de calque dans une liste DXF d'ename.

(vl-list* 1 2 3 4)

Renvoie : (1 2 3 . 4)

(vl-list* 1 2 3 '(4 5 6))

Renvoie : (1 2 3 4 5 6)


Fonctions approchantes en AutoLISP : (list) et (cons)

Il n'est pas question ici de dénigrer AutoLISP mais je vous prie de noter qu'avec ce dernier exemple pour réaliser ce que fait la ligne de code il eût fallu taper :

(cons 1 (cons 2 (cons 3 '(4 5 6))))

Ce qui renvoie aussi (1 2 3 4 5 6) mais est "moins intuitif", on est d'accord ?

 

Haut de page Retour menu Fonctions VL

vl-member-if

Est-ce que ça existe
dans la liste ?

Détermine si la fonction "prédicat" est vraie pour un des éléments de la liste (list).

Syntaxe : (vl-member-if  FonctionPredicat Lst)
Arguments :
-- FonctionPredicat : une sous routine
-- Lst
: une liste (list)

Fonctionne à peu près de la même façon que (member) à ceci près qu'au lieu de chercher dans la liste une expression équivalente à l'argument, elle cherche la première expression qui vérifie (ou ne vérifie pas) la fonction passée comme argument.

Pour FonctionPredicat , cela peut être n'importe quelle fonction qui accepte un seul argument et renvoie T pour toute condition spécifiée par l'utilisateur.
La valeur de FonctionPredicat peut prendre l'une des formes suivantes :

  • un symbole (nom de fonction)
  • '(lambda (A1 A2) ...)
  • (function 'lambda (A1 A2) ...))

Valeur renvoyée :
Une liste, en commençant par le premier élément qui passe le test et contenant tous les éléments suivants dans l'argument original.
Si aucun des éléments ne réussit la condition de test, (vl-member-if)
renvoie nil.


Pour l'exemple dessinez une ligne ou bien tapez ce code :

(command "_line" '(0 0) '(10 20) "")

Ensuite :

(vl-member-if '(lambda (x) (= (cdr x) "AcDbLine")) (entget (entlast)))

Renvoie : ((100 . "AcDbLine") (10 0.0 0.0 0.0) (11 10.0 20.0 0.0) (210 0.0 0.0 1.0))
Ce qui est le restant de la liste renvoyée par (entget (entlast)) ayant comme début le prédicat trouvé par la fonction lambda, à savoir ce qui est en bleu clair dans la liste complète :
((-1 . <Nom d'entité: 7f745207e70>)(0 . "LINE")(330 . <Nom d'entité: 7f7452039f0>)
(5 . "41F") (100 . "AcDbEntity")(67 . 0)(410 . "Model")(8 . "0")(100 . "AcDbLine")
(10 0.0 0.0 0.0)(11 10.0 20.0 0.0)(210 0.0 0.0 1.0))

Sur la même entité un autre prédicat :

(vl-member-if '(lambda (x) (= (cdr x) "Model")) (entget (entlast)))

Renvoie :

((410 . "Model") (8 . "0") (100 . "AcDbLine") (10 19.047 -6.92579 0.0) (11 62.777 15.1583 0.0) (210 0.0 0.0 1.0))
ce qui nous indique que l'entité choisie est dessinée dans l'espace objet (model)

Et maintenant dessinez une ligne en espace papier et testez ce dernier prédicat :

(vl-member-if
             '(lambda (x) (= (cdr x) "Model"))
              (entget (entlast))
)

Qui va renvoyer : nil car il n'est pas trouvé d'entité "ligne" en espace papier

Fonction similaire AutoLISP : (member)

 

 

Haut de page Retour menu Fonctions VL

vl-member-if-not


Fonction en relation avec la précédente mais à la différence de cette dernière  elle renvoie une chaîne de caractères (list)  si le test n'est pas vérifié (renvoie nil)

Pour le reste, syntaxe et argument c'est parfaitement identique à la fonction : (vl-member-if)

Exemples :

Soit la liste Lst :

(setq lst '((0 0 0) (1 2 0) (-3 5 0) (4 -2 0) (5 9 1)))

La ligne de code suivante :

(vl-member-if-not '(lambda (x) (= 0 (caddr x))) lst)

Renvoie ((5 9 1)), ce qui est le premier point de la liste Lst donnée en argument dont le (caddr) d'un des éléments est différent de 0 (zéro), soit la coordonnée Z (caddr) n'est pas 0 (zéro).

 

 

Haut de page Retour menu Fonctions VL

vl-position

Trouver la position d'un élément

 

Fonction qui va renvoyer la position d'un élément donné en premier argument dans une liste (list) donnée en deuxième argument.

Syntaxe : (vl-position symbol Lst)
Arguments :
Premier argument : symbol peut être de type :
- Nombre entier (integer),
- Nombre réel (real),
- Chaîne de caractères (string),
- Liste (list),
File,
- Symbol,
- Nom d'entité (ename),
- T ou nil .

Deuxième argument :  Lst une liste (list) non nil.

Valeur renvoyée :
Nombre entier (integer) précisant la position de l'argument 1 symbol dans l'argument 2 Lst ou nil si pas trouvé.

Le premier élément de la liste Lst (argument 2) est en position 0 (zéro), le deuxième en position 1 et ainsi de suite...

 

Exemples :

Soit la variable "ListTest" renseignée ainsi :

(setq ListTest (list "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"))

La ligne de code :

(vl-position "g" ListTest )

Renvoie : 6 ,
La lettre "g" est en septième position dans la liste (list) mais comme précisé dans l'encart d'alerte la lettre "a" est en position 0 (zéro) donc 6 est bien la position de la lettre "g" dans ce cas de figure.

En mettant un symbol en premier argument le résultat est identique :

(vl-position (chr 103) ListTest )

Le code ascii de la lettre "g" est bien 103 et le résultat de la ligne de code précédente est bien 6 ce qui est la position de la lettre "g" dans la liste (list) donnée en argument 2.

Si l'argument 1 n'est pas trouvé dans la liste (list) :

(vl-position "k" ListTest )

La fonction renvoie nil.

Haut de page Retour menu Fonctions VL

vl-list-length

Longueur d'une liste (list)

 

Ce qu'on entend par longueur d'une liste (list) n'est pas une distance (au sens de longueur) mais un nombre d'éléments.

Syntaxe : (vl-list-length Lst)

Argument : Lst Un seul argument sous forme de liste (list)

Exemples :

(vl-list-length nil)

Renvoie 0, et là on se rend compte que nil peut être une liste vide, donc de longueur 0 (zéro).

(vl-list-length '(1 2))

Renvoie 2

(vl-list-length '(1. 2))

Renvoie nil, car l'argument est une paire pointée (dotted pair) et non une liste (list).

Fonction équivalente en AutoLISP : (length).

 

Haut de page Retour menu Fonctions VL

vl-remove

Retirer un élément d'une liste
(list)

 

Syntaxe : (vl-remove ElementToRemove Lst)

Arguments :
Premier argument : ElementToRemove peut être de type :
- Nombre entier (integer),
- Nombre réel (real),
- Chaîne de caractères (string),
- Liste (list),
File,
- Symbol,
- Nom d'entité (ename),
- T ou nil .

Deuxième argument : Lst
- Une liste (list)

Valeur renvoyée :
Une liste (list) ne contenant plus ElementToRemove
ou la liste originale Lst (deuxième argument) si ElementToRemove n' a pas été trouvé.

Exemples :

Soit la liste (list) :

(setq lst '(1 2 3 4 5))

à laquelle on veut retirer la valeur 1

(setq lst (vl-remove 1 lst))

Renvoie : (2 3 4 5) dans la nouvelle valeur de variable "lst"

et si on repart de la première liste et qu'on fait :

(vl-remove 6 lst)

Renvoie : (1 2 3 4 5), ce qui est la liste originale puisque 6 donné en premier argument n'a pas été trouvé dans la liste (list) donnée en deuxième argument.

Soit les listes (list) :

1
2
(setq lst (list '(1 2 3) '(4 5 6)))
(setq a-retirer '(4 5 6))
(vl-remove a-retirer lst)

renvoie : ((1 2 3))

 

 

Haut de page Retour menu Fonctions VL

vl-remove-if

Retirer un élément d'une liste
avec test

Fonction pour retirer certains éléments d'une liste (list)  qui échouent au test d'une fonction "prédicat" qui renvoie tous les éléments de la liste fournie en argument qui échouent à cette fonction de test

Syntaxe :  (vl-remove-if  FonctionPredicat Lst)

Arguments :
- FonctionPredicat : une sous routine
-
Lst: une liste (list)

Pour la FonctionPredicat , cela peut être n'importe quelle fonction qui accepte un seul argument et renvoie T pour toute condition spécifiée par l'utilisateur.
La valeur de la fonction prédicat p
eut prendre l'une des formes suivantes :

  • un symbole (nom de fonction)
  • '(lambda (A1 A2) ...)
  • (function 'lambda (A1 A2) ...))

Valeur renvoyée : Une liste (list) ou nil.

Soit la liste "list-test" :

(setq list-test (list pi t "a" 1 2.56))

La ligne de code suivante va renvoyer une liste issue de "list-test" en ayant retiré tout ce qui est symbol dans la liste "list-test" via la fonction (boundp) et déclarer une nouvelle variable "list-sans-symbol" :

(setq list-sans-symbol (vl-remove-if 'boundp list-test))

Contenu de la variable "list-sans-symbol" : (3.14159 "a" 1 2.56).

Voir les fonctions :

  • (type) pour tester un élément de la liste
  • (boundp) pour tester si c'est un symbol (SYM).
  • (atoms-family) pour savoir si l'élément est défini comme symbol

 

 

Haut de page Retour menu Fonctions VL

vl-remove-if-not

Retirer un élément d'une liste avec test (bis)

Fonction inverse (dans le test) de la précédente

C'est à dire que (vl-remove-if-not) va renvoyer tous les éléments de la liste fournie en argument qui réussissent la fonction de test.

Tout le reste, syntaxe et arguments est parfaitement identique à (vl-remove-if).

Pour reprendre les mêmes exemples que la fonction servant de référence :

Soit la liste "list-test" :

(setq ListTest (list pi t "a" 1 2.56))

La ligne de code suivante va renvoyer une liste issue de "list-test" en ayant retiré tout ce qui n'est pas symbol dans la liste "ListTest" via la fonction (boundp) et déclarer une nouvelle variable "list-sans-symbol" :

(setq ListDesSymbol (vl-remove-if-not 'boundp list-test))

Contenu de la variable "ListDesSymbol " : (T)
C'est bien la liste de départ fournie en argument "list-test" expurgée de tous ses éléments n'étant des symbol.

Haut de page Retour menu Fonctions VL

 


vl-some

Vérifie si le prédicat est "non nil"

La fonction (vl-some) passe le premier élément de chaque liste fournie en tant qu'argument à la fonction de test, puis à l'élément suivant de chaque liste, et ainsi de suite.
L'évaluation s'arrête dès que la FonctionPredicat renvoie une valeur non nulle pour une combinaison d'arguments, ou jusqu'à ce que tous les éléments aient été traités dans l'une des listes.

Syntaxe : (vl-some FonctionPredicat Lst [lst ...])

Pour la FonctionPredicat , cela peut être n'importe quelle fonction qui accepte autant d'arguments qu'il y a de listes fournies et renvoie T sur une condition spécifiée par le code.

La valeur de la FonctionPredicat peut prendre l'une des formes suivantes :

  • un symbole (nom de fonction)
  • '(lambda (A1 A2) ...)
  • (function 'lambda (A1 A2) ...))

Arguments : une liste (list) ou des listes.

Valeur renvoyée : une liste (list) ou nil.

Exemples :

Deux éléments consécutifs égaux dans une liste (list) donnée en argument (une seule),
Soit la liste (list) pour le test :

(setq liste-test (list 1 2 3 4 4 5 6))

La ligne de code suivante :

(vl-some '= liste-test (cdr liste-test ))

Renvoie : T, car deux éléments consécutifs sont égaux dans la liste (4).
le traitement équivaut à ces séries d'opérations :

(= 1 2 ) => nil
(= 2 3) => nil
(= 3 4) => nil
(= 4 4) => T ; et l'évaluation s'arrête ici.

 

Deux éléments consécutifs égaux dans deux listes (list) données en argument .
Soit les listes (list) pour le test :

(setq liste1 (list 0 2 7 10))
(setq liste2 (list 1 2 7 10))

la ligne de code suivante :

1
2
3
4
5
6
7
8
9
(setq PremierElementEgal 
      (vl-some '(lambda (j k)
           (if (= j k)
               j
           );_ Fin de if
       );_ Fin de lambda
     liste1 liste2
     );_ Fin de vl-some
);_ Fin de setq

la variable "PremierElementEgal" va prendre la valeur 7

 

 

Haut de page Retour menu Fonctions VL

vl-sort

Trier les éléments dans une liste


Cette fonction va trier les éléments dans une liste en utilisant une fonction de comparaison donnée en argument.

Syntaxe : (vl-sort lst fonction-compare)

Arguments :
lst : une liste (list) à trier
fonction-compare : une sous-routine ou un symbol

fonction-compare peut prendre l'une des formes suivantes :

  • un symbole (nom de fonction)
  • '(lambda (A1 A2) ...)
  • (function 'lambda (A1 A2) ...))

Valeur renvoyée : une liste (list).
Ce sera une liste contenant les éléments de lst dans l'ordre spécifié par la fonction de comparaison.
Les éléments en double auront été éliminés de la liste.

Exemples :

Trier des éléments numériques :

Soit la liste de départ "lst-depart" suivante :

(setq lst-depart (list 3 10 7 8 44 3 2 1 3))

Pour la trier dans le sens des nombres croissants (le plus petit en premier) :

(setq lst-triee (vl-sort lst-depart '< ))

le contenu de la variable "lst-triee" est celui-ci : (1 2 3 7 8 10 44)

(setq lst-depart (list 3.1 2.9 3.12 2.91 43 1 3))
(setq lst-triee (vl-sort lst-depart '< ))

Le contenu de la variable "lst-triee" est celui-ci : (1 2.9 2.91 3 3.1 3.12 43)

Trier des éléments alphanumériques :

Soit la liste de départ "lst-depart" suivante :

(setq lst-depart (list "a" "e" "z" "b" "e" "d" "r"))
(setq lst-triee (vl-sort lst-depart '< ))

Le contenu de la variable "lst-triee" est celui-ci : ("a" "b" "d" "e" "e" "r" "z")

 

Encore plus fort:
Trier une liste de coordonnées dans le sens croissant des valeurs de la coordonnée X

Admettons qu'une autre routine nous ait permis de créer une liste de points ainsi formatée :
((3 1) (2 2) (1 3)) et que cette liste (list) soit affectée à la variable "liste-points",
les lignes de code suivantes vont écraser la valeur de "liste-points"
en en créant une autre (liste aussi) mais classée dans l'ordre des X.

1
2
3
4
5
6
7
8
(setq liste-points
   (vl-sort liste-points
      (function (lambda (e1 e2)
                  (< (car e1) (car e2))
                ) ;_ Fin de lambda
      ) ;_ Fin de function
   ) ;_ Fin de vl-sort
) ;_ Fin de setq

Le nouveau contenu de "liste-points" est celui-ci : ((1 3) (2 2) (3 1)), exactement les mêmes valeurs mais triées dans le sens croissant des X

Et si on veut trier la même liste dans le sens croissant des Y, qu'à cela ne tienne remplaçons le (car) dans la fonction (lamba) par un (cadr) et bingo !

1
2
3
4
5
6
7
8
(setq liste-point 
      (vl-sort liste-points
               (function (lambda (e1 e2)
                         (< (cadr e1) (cadr e2))
                         ) ;_ Fin de lambda
                ) ;_ Fin de function
      ) ;_ Fin de vl-sort
 ) ;_ Fin de setq

Le nouveau contenu de "liste-points" est celui-ci : ((3 1) (2 2) (1 3))), exactement les mêmes valeurs mais triées dans le sens croissant des Y.

 

Haut de page Retour menu Fonctions VL

 

vl-sort-i

Trier par index les éléments dans une liste


Cette fonction est très ressemblante à la fonction (vl-sort) à cela près qu'elle ne va pas renvoyer une liste (list) triée des éléments de la liste initiale donnée en argument mais une liste (list) avec les positions (les index) de l'ordre des éléments de la liste initiale.
Un peu confus le jargon du garçon !!! continuons... les exemples arrivent.

Syntaxe :  (vlsort-i lst FonctionDeComparaison)

Arguments :
lst : une liste (list) qu'on va trier.
FonctionDeComparaison : une sous-routine (subroutine). Cela peut être n'importe quelle fonction qui accepte deux arguments et renvoie T (ou toute valeur non nil) si le premier argument précède le second dans l'ordre de tri.

Notez bien le "i" en fin de nom de fonction pour vous rappeler qu'on parle d'Index.

Tout ce qui est syntaxe et arguments est identique à la fonction (vlsort), je ne répète pas car vous étiez là lors du cours sur (vlsort) ... (hihi).

Exemples :

Soit la liste de départ :

(setq liste-depart (list "a" "d" "f" "c"))

On va la trier dans l'ordre décroissant, (le plus grand en premier) :

(setq list-depart-index (vl-sort-i liste-depart '>))

Le contenu de la variable "list-depart-index" est celui-ci : (2 1 3 0)
mais qu'est-ce que ça signifie ???
La liste triée serait ("f" "d" "c" "a") et pour comprendre le résultat (2 1 3 0) :
"f" est le troisième élément dans la liste d'origine donc l'index 2 (premier chiffre de la variable obtenue),
"d" est le deuxième élément (index 1) ....

 

Haut de page Retour menu Fonctions VL

 

vl-every

Vérifie si le prédicat est vrai
pour chaque combinaison d'éléments

 

La fonction (vl-every) passe le premier élément de chaque liste fournie en tant qu'argument à la fonction de test, suivi de l'élément suivant de chaque liste, et ainsi de suite.
L'évaluation s'arrête dès que l'une des listes est épuisée.

Syntaxe : (vl-every FonctionPredicat Lst [lst ...])

Arguments :
FonctionPredicat :  une sous-routine (subroutine) ou un symbole (symbol)
Pour la FonctionPredicat , cela peut être n'importe quelle fonction qui accepte un seul argument et renvoie T pour toute condition spécifiée par l'utilisateur.
La valeur de la fonction prédicat p
eut prendre l'une des formes suivantes :

  • un symbole (nom de fonction)
  • '(lambda (A1 A2) ...)
  • (function 'lambda (A1 A2) ...))

Lst : une liste (list) : la liste qui doit être testée ou les listes qui doivent être testées.

Valeur renvoyée : T ou nil
T, si la fonction de prédicat renvoie une valeur non nil pour chaque combinaison d'éléments sinon c'est la valeur nil qui est renvoyée.

Exemples :

Vérifier si deux listes contiennent les mêmes éléments :

(vl-every '= '(1 2 3 4 5 6) '(1 2 3 4 5 6))

Renvoie T car tous les éléments des deux listes sont identiques

(vl-every '= '(1 2 3 4 5 6) '(1.0 2.0 3.0 4.0 5.0 6.0))

Renvoie T , comparer des entiers (integer) et des réels (real) ne pose pas de souci et donne un résultat correct s'ils sont effectivement égaux

(vl-every '= '(1 2 3 4 5 6) '(1.0 2.0 3.0 4.0 5.0 6.0001))

Renvoie nil, à cause des décimales du dernier élément de la liste en deuxième argument.

Si les deux listes sont n'ont pas le même nombre d'éléments
(vl-every '= '(1 2 3 4 5 6) '(1 2 3 ))

Renvoie T ce qui ne signifie pas pour autant que les listes soient identiques mais que ce que contient la liste1 se retrouve dans la liste2 au même emplacement et la comparaison cesse avec la liste la plus courte

(vl-every '= '(4 5 6 1 2 3) '(1 2 3))

Renvoie nil

Vérifier l'ordre croissant d'une seule liste

(setq Lst (list 0 1 5 8.25 32 123.56))
 (vl-every '<= lst (cdr lst))

Renvoie T car les éléments de Lst sont bien en ordre croissant

(setq Lst (list 0 1 0.24 5 8.25 32 123.56))
 (vl-every '<= lst (cdr lst))

Renvoie nil car les éléments ne sont pas en ordre croissant.

 

Je montre cet exemple car il est renvoyé T dans ce cas de figure surprenant:
(vl-every '= nil '( 1 2 3 4))

La valeur de retour est T parce que (vl-every) répond à la liste nil comme si elle avait atteint la fin de la liste (même si le prédicat n'a encore été appliqué à aucun élément).
Et puisque la fin d'une liste a été atteinte, (vl-every) renvoie une valeur non-nulle (T).

 

Haut de page Retour menu Fonctions VL

 

 

 

avril 2018