【问题标题】:scheme/racket: breaking a list into list of lists方案/球拍:将列表分解为列表列表
【发布时间】:2014-12-07 12:20:34
【问题描述】:

如果我有一个包含 3 个不同对象的列表,这些对象使用全大写字符串彼此分隔,我如何将它们捆绑到一个包含 3 个列表的列表中?

我只做到了

#lang racket

(define (test-string4 lst keyword)
  (let ((kw (string-upcase keyword)))
    (cond ((null? lst) '())
          ((string-upper-case? (car lst))
           (list 

对于 '("POLYLINE" "2" "3" ... "LINE" "2" "3" ...) 的列表 它应该被分解成 '(("POLYLINE" "2" "3" ...) ("LINE" "2" "3" ...))

【问题讨论】:

  • 您能否提供一个示例(输入和预期输出)?
  • 当然,我已经在编辑中这样做了!
  • keyword 的意义何在?您似乎没有在任何地方使用它。

标签: scheme racket


【解决方案1】:

假设string-upper-case? 已经被定义(比如,使用andmap):

(define (string-upper-case? str)
  (andmap char-upper-case?
          (string->list str)))

...我们可以使用来自 SRFI-1 的break 编写一个通用的、更简单、可以说更惯用的实现,将列表拆分为具有以给定条件开头的元素的子列表,在这种情况下是一个全大写的字符串:

(require srfi/1)

(define (splitter pred? lst)
  (if (empty? lst)
      empty
      (let-values ([(data tail) (break pred? (rest lst))])        
        (cons (cons (first lst) data)
              (splitter pred? tail)))))

不管每个元素序列有多长,只要我们遵守关键字是全大写字符串的约定,我们甚至不必传递关键字列表。例如:

(splitter string-upper-case?
          '("POLYLINE" "2" "3" "4" "LINE" "2" "3" "TEST" "1"))

=> '(("POLYLINE" "2" "3" "4") ("LINE" "2" "3") ("TEST" "1"))

【讨论】:

    【解决方案2】:

    我想知道您的数据结构是否真的适合您的需求,但我们开始吧:

    首先我们将定义take-right-until,它将根据谓词f分离最右边的子列表:

    (define (take-right-until lst f)
      (let loop ((spl1 (reverse lst)) (spl2 null) (found #f))
        (if (or found (null? spl1))
            (values (reverse spl1) spl2)
            (let ((c (car spl1)))
              (loop (cdr spl1) (cons c spl2) (f c))))))
    

    测试:

    > (take-right-until '("POLYLINE" "2" "3" "LINE" "4" "5" ) (curryr member '("POLYLINE" "LINE")))
    '("POLYLINE" "2" "3")
    '("LINE" "4" "5")
    > (take-right-until '("POLYLINE" "2" "3") (curryr member '("POLYLINE" "LINE")))
    '()
    '("POLYLINE" "2" "3")
    

    然后test-string4:

    (define (test-string4 lst kwds)
      (define kw (map string-upcase kwds))
      (define f (curryr member kw))
      (let loop ((lst lst) (res null))
        (if (null? lst)
            res
            (let-values (((spl1 spl2) (take-right-until lst f)))
              (loop spl1 (cons spl2 res))))))
    

    测试:

    > (test-string4 '("POLYLINE" "2" "3" "LINE" "4" "5" ) '("polyline" "line"))
    '(("POLYLINE" "2" "3") ("LINE" "4" "5"))
    > (test-string4 '("POLYLINE" "2" "3" "LINE" "4" "5" "SQUARE" "6" "7" "8") '("polyline" "square" "line"))
    '(("POLYLINE" "2" "3") ("LINE" "4" "5") ("SQUARE" "6" "7" "8"))
    

    【讨论】:

      【解决方案3】:

      这似乎是你想要的,虽然string-upper-case? 似乎没有在球拍中定义。

      (define (splitter lst curr)
        (cond ((null? lst)  ; Put current "object" in a list
               (cons curr '()))
      
              ((string-upper-case? (car lst)) ; Starting a new "object"
               (let ((rslt (splitter (cdr lst) (list (car lst)))))
                 (if (null? curr)
                     rslt ; This is the only object
                     (cons curr rslt)))) ; Add last-finished object to front of result
      
              (else ; Continue w/ current "object"
               (splitter (cdr lst) (append curr (list (car lst)))))))
      
      (define (test-string4 lst)
        (splitter lst '()))
      

      【讨论】:

      • 在Scheme中,约定使用else,而不是#t作为最后一个条件。
      猜你喜欢
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-29
      • 2013-11-22
      • 1970-01-01
      相关资源
      最近更新 更多