首页 > 解决方案 > "大部分" 展平嵌套列表

问题描述

我有一个嵌套foo,其中每个元素都是 a bar,我想在不展平foos 的情况下展平bars。
例如:

(special-flatten (foo (foo (bar 2) (bar 3)) (foo (bar 4) (bar 5)))) ;=>
((bar 2) (bar 3) (bar 4) (bar 5))

使用flatten来自球拍的正常不起作用,因为我得到(bar 2 bar 3 bar 4 bar 5).

foo可以嵌套任意深。

有没有一种方法可以做到这一点?

标签: schemeracketflatten

解决方案


如果您有一个谓词来确定何时不应展平子列表,那么您可以这样做。

;; An Element is a value for which element? returns true
;; element? : Any -> Boolean
(define (element? v)
  ...you-have-to-determine-this...)

这个element?谓词应该回答这个问题,“是什么决定了何时不应该展平子列表?” 在您的情况下,这意味着bar(bar 2)和开头的事物(bar 3)

;; An Element is a (cons 'bar Any)
;; element? : Any -> Boolean
(define (element? v)
  (and (pair? v) (equal? (car v) 'bar)))

一旦element?定义了这个谓词,你就可以基于它创建一个 flatten 函数:

;; A NestedFooListofElement is one of:
;;  - Element
;;  - (cons 'foo [Listof NestedFooListofElement])
;; foo-list? : Any -> Boolean
(define (foo-list? v)
  (and (list? v) (pair? v) (equal? (car v) 'foo)))

;; special-flatten : NestedFooListofElement -> [Listof Element]
(define (special-flatten nfle)
  (cond
    [(element? nfle)  (list nfle)]
    [(foo-list? nfle) (append-map special-flatten (rest nfle))]))

使用它:

> (special-flatten '(foo (foo (bar 2) (bar 3)) (foo (bar 4) (bar 5))))
'((bar 2) (bar 3) (bar 4) (bar 5))

推荐阅读