該解決方案不是,即簡單,您必須跟蹤迭代時找到的前一個元素,並且還有一個標誌,告訴您前一個元素是否出現過多次。這裏是我的投籃,假設輸入列表非空(是微不足道的處理情況下,如果輸入列表是空的,作爲練習留給讀者):
(define (removeReps lst)
; we need some extra parameters, use a named let for iteration
(let loop ([lst (cdr lst)] ; list to process, assuming non-empty
[prev (car lst)] ; pick first as "previous" value
[first #t]) ; flag: is this the first element in sequence?
(cond ((null? lst) ; if we reached the end of the list
(if first ; edge case: handle last element
(list prev) ; if it was the first in sequence add it
'())) ; otherwise skip it and end list
; if current element equals previous element
((equal? (car lst) prev)
; skip it, advance recursion and update flag
(loop (cdr lst) prev #f))
; new element, if previous element had exactly one repetition
(first
; add it to output, advance recursion, update prev and flag
(cons prev (loop (cdr lst) (car lst) #t)))
; new element, if previous element had more than one repetition
(else
; skip it, advance recursion, update prev and flag
(loop (cdr lst) (car lst) #t)))))
UPDATE
我真的很喜歡@Haskell中的@acs的實現:更高層次,並利用現有的過程而不是顯式遞歸,它適用於空列表,並且轉換爲Scheme並不困難(但是在Scheme中比在Haskell中更詳細)。這裏有另外一個選擇,使用球拍和SRFI-1的span
程序,看看@ chris的回答,看看它是如何工作的解釋:
(require srfi/1) ; import `span`
(define (group lst)
(match lst
['() '()]
[(cons x xs)
(let-values (((ys zs) (span (curry equal? x) xs)))
(cons (cons x ys) (group zs)))]))
(define (removeReps lst)
(filter-map (lambda (x) (and (= (length x) 1) (first x)))
(group lst)))
或者更便攜,而無需使用特定的球拍程序和特殊形式:
(require srfi/1) ; import `span`
(define (group lst)
(if (null? lst)
'()
(let ((x (car lst))
(xs (cdr lst)))
(let-values (((ys zs) (span (lambda (e) (equal? e x)) xs)))
(cons (cons x ys)
(group zs))))))
(define (removeReps lst)
(map car
(filter (lambda (x) (= (length x) 1))
(group lst))))
讓我們測試了一些邊緣案件的程序 - 它按預期工作與任何上述實施方式的:
(removeReps '(a b a a a c c))
=> '(a b)
(removeReps '(x a a x b b x c c x))
=> '(x x x x)
(removeReps '(a a a))
=> '()
(removeReps '(a b b c c))
=> '(a)
(removeReps '(a a b b c c d))
=> '(d)
這是一個不錯的Haskell解決方案,但我認爲OP對Lisp或Scheme實現感興趣...... –
是的。但正如我所說,我不熟悉Scheme;)。我很確定它有與'head','filter','map'等價的等價物。那麼'group'或'span'呢?那麼把我的解決方案翻譯成任何其他功能語言應該是微不足道的。 – chris
當然,在Scheme中有'head'' filter'和'map'的等價物。 'Group'和'span'在標準Scheme中沒有直接的對應關係(儘管''span'在SRFI-1中可用),但看起來很容易翻譯,因爲您指出 –