转置填充空列表的元组列表

时间:2015-10-04 21:46:14

标签: list scheme racket mit-scheme

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

我目前的实施如下:

(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))

我该如何解决?

3 个答案:

答案 0 :(得分:2)

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

; 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 () ()))

答案 1 :(得分:0)

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

 (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))))))))

答案 2 :(得分:0)

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

首先让我们假设一个程序,它将获取一个列表,并返回以下结果:

  1. 包含每个子列表的第一项的列表
  2. 包含每个子列表的其余部分的列表
  3. 遇到的非空列表数
  4. 示例实现可以是:

    (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 '())
    '()