6 votes

Scheme : Comment vérifier si tous les éléments d'une liste sont identiques ?

J'aimerais créer une fonction Scheme qui donne vrai si on lui passe une liste composée entièrement d'éléments identiques. Une telle liste serait '(1 1 1 1 1). Elle donnerait faux avec quelque chose comme "(1 2 1 1)".

Voici ce que j'ai jusqu'à présent :

    (define (list-equal? lst)
      (define tmp (car lst))
      (for-each (lambda (x) 
                   (equal? x tmp))
                 lst)
      )

Il est clair que c'est incorrect, et je suis nouveau dans ce domaine. Je suppose que je n'arrive pas à exprimer l'étape où je suis censé retourner #t o #f .

Merci d'avance !

EDIT : J'ai bricolé un peu et j'ai trouvé une solution qui semble fonctionner très bien, et avec une quantité minimale de code :

(define (list-equal? lst)
 (andmap (lambda (x) 
        (equal? x (car lst)))
      lst))

Merci encore pour votre aide à tous.

3voto

andrykonchin Points 958

Quantité minimale de code, si vous ne vous souciez pas du fait que cela ne fonctionne que pour les nombres :

(define (list-equel? lst)
  (apply = lst))

Exemples :

> (list-equel? '(1 1 2 1))
#f
> (list-equel? '(1 1 1 1))
#t
> (list-equel? '(1))
#t

2voto

Lorenz Forvang Points 134

En andmap est une bonne solution, mais si andmap n'est pas disponible, vous pouvez utiliser ceci. Il utilise les opérations de base (and, or, null check, equality check) et gère les listes vides et les listes à un élément. Similaire à l'implémentation de Sean, mais aucune définition d'aide n'est nécessaire.

(define (list-equal? args)
  (or (or (null? args)
          (null? (cdr args)))
      (and (eq? (car args) (cadr args))
           (list-equal? (cdr args)))))

0voto

Daniel Points 2200
(define (list-equal? lst)
    (if (= (cdr lst) null)
        true
        (and (equal? (car lst) (cadr lst))
             (list-equal? (cdr lst)))))

0voto

Sean Devlin Points 941

Essayez quelque chose comme ça :

(define (list-equal? lst)
 (define (helper el lst)
  (or (null? lst)
      (and (eq? el (car lst))
           (helper (car lst) (cdr lst)))))
 (or (null? lst)
     (helper (car lst) (cdr lst))))

Ce n'est peut-être pas l'implémentation la plus propre, mais je pense qu'elle traitera correctement les cas des listes vides et des listes à un élément.

0voto

sepp2k Points 157757

Dans R6RS, il y a le for-all qui prend un prédicat et une liste, et retourne #t si le prédicat retourne vrai pour tous les éléments de la liste et #f autrement, ce qui est exactement ce dont vous avez besoin ici.

Donc, si vous utilisez R6RS (ou tout autre dialecte de schéma qui a l'attribut for-all ), vous pouvez simplement remplacer for-each con for-all dans votre code et cela fonctionnera.

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