簡體   English   中英

比較列表的結構相等性

[英]Comparing structure equality of lists

如何檢查Scheme中兩個列表的結構相等? 例如, (a (b) (cd))等於(ab (cd) (efg)) ,並且(ab)等於(abc) 列表的數據內容無關緊要,只有嵌套列表的結構層次結構,即子列表的數量,以及這些子列表的子列表的數量,等等。

我創建了一個名為eqStruct的函數,它將兩個列表作為參數。 它應該計算每個列表中的子列表數量ab ,然后返回一個布爾值。 該函數查看列表a每個元素,然后查看列表b每個元素。 它使用cd作為ab中子列表數量的計數器,當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) (具有結構((()())())右。如果你只想檢查ab是否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)為真),或者它是一個有carcdr 空列表的結構顯然是空列表,所以我們只能返回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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM