3 votes

Comment itérer à travers une structure ?

Si j'ai une liste comme: [atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)], comment pourrais-je 'itérer' à travers les éléments d'une des structures atm ?

Par exemple, pour atm(abd, bubu, ha), je voudrais écrire abd, bubu et ha.

Le problème est que les structures ont une longueur variable.

Y a-t-il un moyen de transformer la structure en une liste? Merci.

3voto

mat Points 7998

Utilisation de (=..)/2

@TopologicalSort a déjà donné une belle réponse, en utilisant (=..)/2 pour convertir un terme en une liste de foncteur et d'arguments.

Cela résout évidemment le problème immédiat de manière très générale.

Cependant, cela présente également ses propres inconvénients : Tout d'abord et surtout, (=..)/2 n'est pas une relation générale. Par exemple, nous avons :

?- X =.. Y.
**ERREUR: Les arguments ne sont pas suffisamment instanciés**

Cela signifie que nous ne pouvons pas utiliser cette construction pour générer des solutions. Cela fonctionne uniquement si ses arguments sont suffisamment instanciés.

Deuxièmement, l'utilisation de (=..)/2 s'accompagne également d'un surcoût en temps et en mémoire pour construire et représenter une liste en plus du terme qui est déjà là sous une forme différente. (Et, mutatis mutandis, dans l'autre sens également bien sûr.)

Il peut donc être intéressant de se demander : Existe-t-il différentes manières de résoudre cette tâche ? Sont-elles mieux adaptées ?

Alternative 1 : Le faire manuellement

Comment te convertir ? Laisse-moi compter les moyens.

À partir de l'exemple que vous citez, nous devons être capables de gérer— dans l'ordre de leur apparition— des termes des formes suivantes :

  • atm/3
  • atm/1
  • atm/2
  • atm/4

Le point ici est que le nombre de cas montrés est fini, et donc nous pouvons facilement tous les gérer de cette façon :

atm\_list(atm(A),       \[A\]).
atm\_list(atm(A,B),     \[A,B\]).
atm\_list(atm(A,B,C),   \[A,B,C\]).
atm\_list(atm(A,B,C,D), \[A,B,C,D\]).

Pour convertir une liste de tels termes, vous pouvez utiliser maplist/2 :

?- Ls = \[atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)\],
   maplist(atm\_list, Ls, Lists).
Ls = \[atm(abd, bubu, ha), atm(aei), atm(xyz, huhu), atm(aabb, a, e, x)\],
**Lists = \[\[abd, bubu, ha\], \[aei\], \[xyz, huhu\], \[aabb, a, e, x\]\].**

Un avantage majeur est que cette relation est très générale et peut également être utilisée pour générer des réponses :

?- atm_list(A, Ls). A = atm(_27464, _27466, _27468), Ls = [_27464, _27466, _27468] ; A = atm(_27464), Ls = [_27464] ; A = atm(_27464, _27466), Ls = [_27464, _27466] ; A = atm(_27464, _27466, _27468, _27470), Ls = [_27464, _27466, _27468, _27470].

C'est également plus efficace que d'utiliser (=..)/2. Clairement, cela ne peut être fait que si le nombre de cas émergents est fini. (Exercice : Écrivez un programme Prolog qui génère des clauses pour tous les entiers de 1 à N.)

Alternative 2 : Utiliser des listes

Il existe plusieurs critères bien connus pour juger si les listes sont une structure de données appropriée. Par exemple :

  • L'liste vide a-t-elle un sens dans votre cas d'utilisation ?
  • Y a-t-il des cas sensibles pour toutes les longueurs possibles ?
  • Etc.

Seule vous pouvez répondre à cette question pour votre cas d'utilisation particulier, donc je montre seulement à quoi cela pourrait ressembler : Supposez que vous représentez toute votre liste initiale de la manière suivante :

\[\[abd,bubu,ha\],\[aei\],\[xyz,huhu\],\[aab,a,e,x\]\]

Alors, toute la question n'existe même pas, car les éléments sont déjà spécifiés en tant que listes. Ainsi, il n'y a plus besoin de convertir quoi que ce soit.

2voto

Topological Sort Points 1546

Bien sûr.

Si Premier est atm(abd,bubu,ha) (par exemple), ce code le divisera en une liste que vous pouvez parcourir.

Premier =.. Liste.

Ensuite, Liste sera [atm, abd, bubu, ha].

Je ne sais pas si cela fonctionne dans votre version particulière de PROLOG. J'utilise SWI-PROLOG. Sinon, peut-être que votre version a un prédicat similaire.

Pour plus d'informations, voir http://www.swi-prolog.org/pldoc/doc_for?object=(%3D..)/2.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X