2014-11-21 79 views
0

我想檢查列表中的第一個原子與列表中的其他原子,所以如果第一個原子是3並且第三個原子是三個,我想評估它是錯誤的。檢查第一個原子對列表中的其他原子

我有類似

(define (doubles a_list) (cond ((null? a_list) #t) (not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list)))

我有一種感覺,這將只檢查原子彼此相鄰,而不是一個原子與他們的休息。我能做什麼來檢查第一個項目的所有項目?

回答

1

我有我的茶,我的代碼審查帽子和幾分鐘的空閒時間。你知道現在幾點了。


你想要的是一個謂詞,它會告訴你是否有列表中第一個原子的重複。

(define (doubles a_list) 
    (cond ((null? a_list) #t) 
     (not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list))) 

無論其他什麼,這不會工作,因爲它有不平衡的括號。

(define (doubles a_list) 
    (cond ((null? a_list) #t) 
     (not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list))))) 

這個修訂版將無法工作,因爲它在case畸形的第二句話。奇怪的是,它似乎評價很好,但是當你調用它,你會得到一個奇怪的錯誤信息

Welcome to Racket v5.3.6. 
> (define (doubles a_list) 
    (cond ((null? a_list) #t) 
     (not ((eq? (car a_list) (car (cdr a_list)))) (doubles(cdr a_list))))) 
> (doubles (list 1 2 3 4 5 6 7 3)) 
application: not a procedure; 
expected a procedure that can be applied to arguments 
    given: #f 
    arguments...: [none] 
> 

的直接原因是由於圍繞這一額外的括號的該位

... ((eq? (car a_list) (car (cdr a_list)))) ... 

表達,它實際上意味着什麼

「看看a_list的第一個元素是否與第二個元素相同,然後將該檢查的結果作爲函數調用」。

這不是你想要的。正確的分辨率是not到這些parens,這將使有效的cond條款。

(define (doubles a_list) 
    (cond ((null? a_list) #t) 
     ((not (eq? (car a_list) (car (cdr a_list)))) 
     (doubles (cdr a_list))))) 

不能在方案空列表上調用car。這對Common Lisp中的「fine」的一些定義很好,但會在這裏給你一個錯誤。

> (define (doubles a_list) 
    (cond ((null? a_list) #t) 
     ((not (eq? (car a_list) (car (cdr a_list)))) 
     (doubles (cdr a_list))))) 
> (doubles (list 1 2 3 4 5 6 7 3)) 
car: contract violation 
    expected: pair? 
    given: '() 
> 

此錯誤的原因是,你檢查a_list是否null?,但再後來就打電話(car (cdr a_list))。在a_list類似於(3)的情況下,您會收到此錯誤。對此問題進行修復正在檢查是否a_list或其cdr現在null?

(define (doubles a_list) 
    (cond ((or (null? a_list) (null? (cdr a_list))) #t) 
     ((not (eq? (car a_list) (car (cdr a_list)))) 
     (doubles (cdr a_list))))) 

> (doubles (list 1 2 3 4 5 6 7 3)) 
#t 

,我們已經有了一個版本的功能不報錯了,讓我們看看你的邏輯。在列表中找到雙打的過程

  • 的長度爲零或一個名單,答案是假的,因爲不可能有雙打列表中的短於兩個元素
  • 否則,檢查第一清單中的元素在其餘部分。
  • 如果是,答案是真實的,因爲我們已經發現重複

現在,你已經命名的功能doubles,但你的散文的解釋告訴我,這真的應該已經unique-first?。因爲你不是在尋找雙打,你的目的是要檢查你的列表中的第一個元素是否在同伴中是唯一的。你真正想要做的是

  • 的長度爲一的名單,答案是正確的,因爲是單一的元素必須是唯一的(我會假設你想要的長度爲零的列表相同,但根據應用程序可能沒有實際意義)
  • 否則,請檢查列表的第一個元素是否不在其餘。

這相當於

(define (unique-first? a_list) 
    (if (or (null? a_list) (null? (cdr a_list))) 
     #t 
     (not (member? (car a_list) (cdr a_list))))) 

member?功能是相當簡單的,並且適用於同樣的原則。

(define (member? elem lst) 
    (cond ((null? lst) #f) 
     ((eq? elem (car lst)) #t) 
     (else (member? elem (cdr lst))))) 

最後,一對夫婦的造型加分。 Scheme的慣例是命名帶有尾部?的謂詞,它會向您的函數的調用者暗示它將返回#t#f(我已經完成了上述操作),並且使用spinal-case而不是snake_case作爲名稱。

(define (unique-first? a-list) 
    (if (or (null? a-list) (null? (cdr a-list))) 
     #t 
     (not (member? (car a-list) (cdr a-list))))) 
+0

主席先生,在您的許可下,我是否可以採用您的命名慣例爲'unique-first?'? :) – xbug 2014-11-21 16:49:10

+0

@xbug - 當然。去堅果:) – Inaimathi 2014-11-21 16:56:08

+0

非常感謝:-) – xbug 2014-11-21 16:57:43

2

你想你的列表的前兩個元素反覆比較,減少了cdr,當您去:

(define (unique-first? x) 
    ; uncomment the following line to trace the execution 
    ;(display x) (newline) 
    (or (null? x) (null? (cdr x)) 
     (and (not (eq? (car x) (cadr x))) 
      (unique-first? (cons (car x) (cddr x)))))) 

注意在特殊的情況:

  • (unique-first? '()) - >#t
  • (unique-first? '(a)) - >#t

(其確實驗證了「第一個元素沒有出現兩次」標準)。

+0

什麼是cddr命令應該做的? – guevarak12 2014-11-21 19:37:12

+0

'(cddr x)'簡單地擴展爲'(cdr(cdr x))'。 – xbug 2014-11-21 19:40:50

+0

如果我想擴展它以檢查列表中的每個原子不是重複的,我可以編輯最後一行到 (unique-first?(cons(car x)(cdr x)))))) ? – guevarak12 2014-11-21 19:44:19