[英]Comparing structure equality of lists
如何檢查Scheme中兩個列表的結構相等? 例如, (a (b) (cd))
等於(ab (cd) (efg))
,並且(ab)
等於(abc)
。 列表的數據內容無關緊要,只有嵌套列表的結構層次結構,即子列表的數量,以及這些子列表的子列表的數量,等等。
我創建了一個名為eqStruct
的函數,它將兩個列表作為參數。 它應該計算每個列表中的子列表數量a
和b
,然后返回一個布爾值。 該函數查看列表a
每個元素,然后查看列表b
每個元素。 它使用c
和d
作為a
和b
中子列表數量的計數器,當atom?
在列表元素上調用時返回false。 在每次查看列表的第一個原子之后,列表被設置為等於它自己而沒有它的第一個項目(list-tail),並且當整個列表'a和'b被查看時, unless
循環終止。
(define (eqStruct 'a 'b)
(define c 0)
(define d 0)
(define (atom? x) (not (pair? x)))
(unless (null? a)
(unless (atom? (first a)) (set! c (+ c 1))
(set! a (list-tail a 1))
)
(unless (null? b)
(unless (atom? (first b)) (set! d (+ d 1))
(set! b (list-tail b 1))
)
(eq? c d)
)
最后一行應該是一個返回語句,因為我希望函數是一個謂詞,並返回列表是否具有相同的結構,一個布爾值,但我不知道如何實現這一點,或者如果我甚至以正確的方式思考這個問題。
您的代碼(以及您對它的評論)指出了對某些Racket結構的一些誤解。
一個大問題是, unless
不是循環結構; 它只是有條件地執行一些代碼。 例如,如果您評估(unless (= 1 2) (display 'x))
,則不會永久打印x
,而只打印一次。 這意味着您獲得的代碼將不會按照您的預期執行。
但是,如果我們假設那樣(以便我們了解您的代碼嘗試做什么),那么您就有了一個合理的想法。 你試圖迭代列表a
並計算它有多少列表a
元素。
(unless (null? a)
(unless (atom? (first a)) (set! c (+ c 1))
(set! a (list-tail a 1))
)
如果您的列表總是只有一層深, 那么這是個好主意。 例如,你正確地檢查((ab) c)
和((a) bc)
,但你不會得到((a (b)) c)
(具有結構((())())
)和(((a) (b)) c)
(具有結構((()())())
右。如果你只想檢查a
和b
是否a
與列表相同數量的元素,如果unless
是一個循環結構),你就會走上正軌。
您嘗試從每個輸入列表中提取表示列表結構(在您的情況下是一個數字)並比較這些代表值的一般方法是一個很好的方法。 我認為你只需要使用稍微不同的代表值,並且稍微有點不同( eq?
對你的情況來說很好,我想,但我想到的代表值需要equal?
)。
請注意,鑒於它們的定義方式,結構可以equal?
。 鑒於這種觀察,我認為最簡單的方法是編寫一個采用列表並返回其規范結構的過程。 還要注意通過使用list?
在內部if
,我們正確處理具有(() ())
結構的(() ())
((ab) ())
(() ())
。
(define (structure list)
(if (null? list)
list
(if (list? (car list))
(cons (structure (car list)) (structure (cdr list)))
(structure (cdr list)))))
> (structure '(a (b) (c d)))
(() ())
> (structure '((a b) ()))
(() ())
然后,為了比較兩個列表的結構,您可以只獲取兩個列表的結構並進行比較。
(define (structure-equal? list1 list2)
(equal? (structure list1)
(structure list2)))
> (structure-equal? '(a b) '(a b c))
#t
> (structure-equal? '(a (b) (c d)) '(a b (c d) (e f g)))
#t
了解為何如此equal?
在結構上的工作不應該太難,但理解structure
如何工作更重要。 讓我們更仔細地看一下
(define (structure list)
(if (null? list)
list ; or '()
(if (list? (car list))
(cons (structure (car list)) (structure (cdr list)))
(structure (cdr list)))))
我們假設進入的list
實際上是一個列表。 這意味着它是空列表()
(所以(null? list)
為真),或者它是一個有car
和cdr
。 空列表的結構顯然是空列表,所以我們只能返回list
(因為它是空的)。 另一種情況比較復雜; list
是一對,其car
是一些值,其cdr
是列表的其余部分。 如果car
也是一個列表,那么它會向list
的結構添加一些東西,但如果不是,那么它只是一些元素,並沒有對列表的結構做出貢獻。 更具體地說,當list
是對(x . y)
:
x
是一個列表,那么(x . y)
(<structure of x> . <structure of y>)
是(<structure of x> . <structure of y>)
x
不是列表,那么(x . y)
的<structure of y>
是<structure of y>
。 這應該解釋內部if
的邏輯(我們用(cons ab)
創建一對(a . b)
(cons ab)
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.