2011-09-06 97 views
4

我想創建一個Scheme函數,如果它傳遞一個完全由相同元素組成的列表,則返回true。這樣的清單將是'(1 1 1 1)。它會產生錯誤,如'(1 2 1 1)。Scheme:如何檢查列表中的所有元素是否相同

這是我到目前爲止有:

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

這顯然是不正確的,我是新來這。我想我無法表達我應該退回的步驟#t#f

在此先感謝!

編輯: 我擺弄了一下,發現這似乎工作得很好的解決方案,並用最少的代碼量:再次

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

感謝大家的幫助。

回答

0
(define (list-equal? lst) 
    (if (= (cdr lst) null) 
     true 
     (and (equal? (car lst) (cadr lst)) 
      (list-equal? (cdr lst))))) 
+0

這似乎也不起作用,我認爲它到頭了,並抱怨說它不能在單獨的元素上使用cadr。如果這有所作爲,我正在使用球拍/ Pretty Big。 – Joseph

+0

這將炸燬一個元素的列表。編輯:約瑟夫是正確的,它會炸燬任何名單,當你到它的結尾。 –

+0

@joseph:你說得對。只是我剛剛做出的小改動應該解決它。 – Daniel

-1

因爲這些語言是不好的。嘗試

(define list-equal? 
(lambda (lst) 
    (if (= lst null) 
    (true) 
    (foldr = (car lst) (cdr lst)) 
))) 
+0

這是行不通的。您正在比較列表元素和布爾結果。 – Daniel

0

嘗試這樣:

(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)))) 

這可能不是最乾淨的實現,但我認爲它會正確處理空列表和一個元素列表的情況。

+0

這個效果很好。非常感謝,我想我有這個問題。 – Joseph

0

在R6RS還有的for-all功能,這需要一個謂詞和一個列表,返回#t如果斷言列表中的所有元素#f返回true,否則,這是你在這裏需要什麼。

所以,如果你使用R6RS(或具有for-all功能的任何其它方案方言),你可以在你的代碼for-all更換for-each,它會工作。

+0

這對於我來說是不可能的。但很高興知道我在正確的軌道上。 – Joseph

+0

這將工作,增加一步,你仍然必須檢查'lst'不是空的。 –

+0

@肖恩:是的,好點。這或者拋棄'tmp'變量,並且每次在謂詞中調用'(car lst)'(永遠不會調用空列表來避免這個問題)。 – sepp2k

0

像這樣的東西應該工作:

(define (list-equal? lst) 
    (cond ((< (length lst) 2) #t) 
     (#t (and (equal? (car lst) (cadr lst)) 
      (list-equal? (cdr lst)))))) 
+0

這很好,除了它運行在O(n * n)時間,而不是O(n)時間(因爲對於列表中的每個位置,列表的剩餘部分的長度都會被計算)。如果調整後的基本情況爲'(或(null?lst)(null?(cdr lst)))',那麼它的運行時間會更好,並且更加簡潔。 –

0

其他的答案,在這個線程都顯得過於複雜(我通過他們所有的讀取),所以這裏是我對此採取:

(define (all-equal? lst) 
    (define item (car lst)) 
    (let next ((lst (cdr lst))) 
    (cond ((null? lst) #t) 
      ((equal? item (car lst)) (next (cdr lst))) 
      (else #f)))) 

(它不適用於一個空的列表,如果需要,很容易添加(if (null? lst) #t ...))。

3

如果你不關心它只適用於數字,那麼代碼量很小:

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

例子:

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

絕對是最好的解決方案,我不相信我沒有想到它。好決定。 – JasonFruit

+0

雖然你甚至不需要長度條件。 '(等於?)'沒有參數=>'#t'。 – JasonFruit

+0

只有當您的列表僅包含數字時纔有效。 :-) –

1

andmap解決方案是好的,但如果andmap不可用,你可以用這個。它使用基本操作(和,或者,空檢查,相等檢查)並處理空列表和一個元素列表。與肖恩的實施類似,但沒有幫助者的定義是必要的。

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

'(或1 2 3)'也是合法的。 –

0

短,簡潔的解決方案:

#lang racket 
(define (all-equal? lst) 
    (for/and 
     ([i (in-permutations lst)]) 
    (equal? (first i) (second i)))) 

; TEST CASES 

(require rackunit) 

(check-false (all-equal? '(1 2 3))) 
(check-true (all-equal? '(1 1 1))) 
(check-true (all-equal? '())) 

注意,這裏使用的球拍,所以這可能不是你的計劃的實施工作。

相關問題