【问题标题】:Transpose list of tuples filling with empty lists转置填充空列表的元组列表
【发布时间】:2015-10-04 21:46:14
【问题描述】:

我是 Scheme 的新手,我正在尝试编写一个将 n 列表组合成 n 元组列表的过程。如果列表大小不同,则当相应列表中的元素用完时,元组应包含空列表()

我目前的实现如下:

(define (comb list1 list2)  
    (cond [(empty? list1) empty]
          [(empty? list2) empty]
          [else (cons (list (first list1) (first list2))
                      (comb (rest list1) (rest list2)))]))

但是,当列表中没有更多要组合的项目时,此程序不会生成另一个元组。例如,(comb '(1 2 3 ) '(3 4)) 仅生成 ((1 3) (2 4))

我该如何解决?

【问题讨论】:

    标签: list scheme racket mit-scheme


    【解决方案1】:

    这有点棘手,我认为这对于刚刚学习语言基础的人来说不是一个合适的练习。无论如何,就高阶程序而言,这是我提出的解决方案:

    ; helper procedure for filling a list with arbitrary values at the end
    (define (fill lst val num)
      (append lst
              (build-list num (const val))))
    
    ; helper procedure for transposing a list of lists    
    (define (transpose lsts)
      (apply map list lsts))
    
    ; main procedure
    (define (list-tuples lsts)
      (let* ((lengths    (map length lsts))    ; obtain the length of each sublist
             (max-length (apply max lengths))) ; find out the maximum length
        (transpose                             ; build new sublists element-wise
         (map (lambda (lst len)                ; build sublists of the right length
                (fill lst '() (- max-length len)))  ; fill sublists with '()
              lsts
              lengths))))
    

    诀窍是找到列表的最大长度,然后用该长度构建新列表,最后用'() 填充它们。之后,通过从每个子列表中获取一个元素来构建答案是一件简单的事情。它按预期工作:

    (list-tuples '((m n o) (1) (x y)))
    => '((m 1 x) (n () y) (o () ()))
    

    【讨论】:

      【解决方案2】:

      您需要专门处理其中一个列表为空的情况。以下是我认为你想要的两个列表。

       (define (comb l1 l2)
         (cond 
           ((empty? l1) 
            (cond
              ((empty? l2) '())
              (else (cons (list '() (car l2)) (comb l1 (cdr l2))))))
           (else
             (cond
               ((empty? l2) (cons (list (car l1) '()) (comb (cdr l1) l2)))
               (else (cons (list (car l1) (car l2)) (comb (cdr l1) (cdr l2))))))))
      

      【讨论】:

        【解决方案3】:

        让我们把问题分成两部分。

        首先让我们假设一个过程将接受一个列表,并返回以下结果:

        1. 包含每个子列表的第一项的列表
        2. 包含每个子列表剩余部分的列表
        3. 遇到的非空列表的数量

        一个示例实现可能是:

        (define (split-tuples lst)
          (let loop ((lst lst) (fst null) (rst null) (cnt 0))
            (if (null? lst)
                (values (reverse fst) (reverse rst) cnt)
                (let ((c (car lst)))
                  (if (null? c)
                      (loop (cdr lst) (cons      c  fst) (cons      c  rst) cnt)
                      (loop (cdr lst) (cons (car c) fst) (cons (cdr c) rst) (add1 cnt)))))))
        

        测试:

        > (split-tuples '((m n o) (1) (x y)))
        '(m 1 x)
        '((n o) () (y))
        3
        > (split-tuples '((n o) () (y)))
        '(n () y)
        '((o) () ())
        2
        > (split-tuples '((o) () ()))
        '(o () ())
        '(() () ())
        1
        > (split-tuples '(() () ()))
        '(() () ())
        '(() () ())
        0
        

        现在使用这个过程,我们创建一个循环直到所有子列表都为空的主过程:

        (define (list-tuples lst)
          (let loop ((lst lst) (res null))
            (let-values (((fst rst cnt) (split-tuples lst)))
              (if (zero? cnt)
                  (reverse res)
                  (loop rst (cons fst res))))))
        

        测试:

        > (list-tuples '((m n o) (1) (x y)))
        '((m 1 x) (n () y) (o () ()))
        > (list-tuples '())
        '()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-12
          • 1970-01-01
          • 2021-12-14
          • 2019-11-24
          • 2023-01-14
          • 1970-01-01
          • 2014-01-12
          • 2022-08-18
          相关资源
          最近更新 更多