2009-03-29 7 views

Répondre

21

Si vous devez effectuer une comparaison à l'aide de l'un des opérateurs d'équivalence de construction, vous pouvez utiliser memq, memv, or member, selon que vous souhaitez rechercher l'égalité à l'aide de eq?, eqv?, or equal?, respectivement. Comme vous pouvez le constater, ces fonctions renvoient la sous-liste en commençant par le premier élément correspondant si elles trouvent un élément. C'est parce que si vous recherchez une liste qui peut contenir des booléens, vous devez être capable de distinguer le cas de trouver un #f du cas de ne pas trouver l'élément que vous recherchez. Une liste est une vraie valeur (la seule valeur fausse dans le schéma est #f) de sorte que vous pouvez utiliser dans un contexte le résultat de memq, memv ou member attend un booléen, comme un if, cond, and ou or expression.

> (if (memq 'a '(a b c)) 
    "It's there! :)" 
    "It's not... :(") 
"It's there! :)" 

Quelle est la différence entre les trois fonctions différentes? C'est basé sur quelle fonction d'équivalence ils utilisent pour la comparaison. eq? (et donc memq) teste si deux objets sont le même objet sous-jacent; il est fondamentalement équivalent à une comparaison de pointeur (ou comparaison de valeur directe dans le cas d'entiers). Ainsi, deux chaînes ou listes qui se ressemblent peuvent ne pas être eq?, car elles sont stockées dans des emplacements différents en mémoire. equal? (et donc member?) effectue une comparaison approfondie sur les listes et les chaînes, et donc fondamentalement les deux éléments qui impriment la même chose seront equal?.eqv? est comme eq? pour presque tout sauf des nombres; pour les nombres, deux nombres qui sont numériquement équivalents seront toujours eqv?, mais ils ne peuvent pas être eq? (ce qui est à cause de bignums et des nombres rationnels, qui peuvent être stockés de manière telle qu'ils ne seront pas eq?)

> (eq? 'a 'a) 
#t 
> (eq? 'a 'b) 
#f 
> (eq? (list 'a 'b 'c) (list 'a 'b 'c)) 
#f 
> (equal? (list 'a 'b 'c) (list 'a 'b 'c)) 
#t 
> (eqv? (+ 1/2 1/3) (+ 1/2 1/3)) 
#t 

(Notez que certains comportements des fonctions n'est pas défini par la spécification, et peut donc différer de la mise en œuvre à la mise en œuvre, j'ai inclus des exemples qui devraient fonctionner dans tous les R RS Scheme compatible qui implémente le nombre exact rationnels)

Si vous devez rechercher un élément dans une liste à l'aide d'un prédicat d'équivalence e différent de l'un des construit dans les, vous voudrez peut-être find ou find-tail de SRFI-1:

> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6)) 
'(4 5 6) 
+0

Quel est le nom de la fonction 'memq' court? – Freewind

+1

'memq' fait partie de la famille de fonctions' member', trouvant un élément dans une liste basée sur une sorte d'équivalence (comme les autres mentionnés, 'member' et' memv'). Le 'q',' v', ou le nom complet le relient aux trois fonctions d'équivalence qu'ils utilisent chacun; 'memq' utilise' eq? 'pour tester l'équivalence,' memv' utilise 'eqv?' pour tester l'équivalence, et 'member' utilise' equal? ​​'pour tester l'équivalence. Voir la documentation liée sur les fonctions d'équivalence pour la différence entre elles. –

+0

Merci! Donc 'memq' peut être considéré comme' mem-q', et 'memv' comme' mem-v' – Freewind

0

Vous êtes à la recherche pour « trouver »

Principes de base - Le cas le plus simple est juste (trouver la liste d'entrée), généralement utilisé comme prédicat: « est entrée dans la liste? ». S'il réussit à trouver l'élément en question, il renvoie le premier élément correspondant au lieu de simplement "t". (extrait de second lien.)

http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html

-ou-

http://www.apl.jhu.edu/~hall/Lisp-Notes/Higher-Order.html

+0

La question était sur le schéma, non Lisp commun. –

+0

Eh bien, il a tagué LISP. –

+0

Lire le titre: 'Quelle est la fonction SCHEME pour trouver un élément dans une liste?'. Le schéma est un dialecte de la famille des langages Lisp. –

3

est ici une façon:

> (cond ((member 'a '(a b c)) '#t) (else '#f)) 
#t 
> (cond ((member 'd '(a b c)) '#t) (else '#f)) 
#f 

retourne tout membre à partir de l'endroit où l'élément est ou #f. Un cond est utilisé pour convertir ceci en vrai ou faux.

+0

'# t' est aussi bien, au lieu de' '# t' –

0

Je ne sais pas s'il y a une fonction intégrée, mais vous pouvez en créer un:

(define (occurrence x lst) 
     (if (null? lst) 0  
      (if (equal? x (car lst)) (+ 1 (occurrence x (cdr lst))) 
            (occurrence x (cdr lst)) 
      ) 
     ) 
) 

Vous obtiendrez en retour le nombre d'occurrences de x dans la liste. vous pouvez l'étendre avec true ou false aussi.