将列表拆分为两个 - 一个包含每个第二个元素,另一个包含所有其余元素

时间:2014-05-16 14:01:19

标签: scheme

我正在写一个递归函数(split L) 获取列表L,并返回一个新列表 包含两个子列表,第一个子列表包含L中的每个第二个元素 第二个列表包含不在第一个子列表中的其余元素。

下面 是如何的例子 分裂 应该工作:

(split ‘(1 2 3 4 5 6 7 8) )  ( (1 3 5 7) (2 4 6 8))
(split ‘(cat bird dog horse mouse pig tiger gerbil cow) )
( (cat dog mouse tiger cow) (bird horse pig gerbil)) 

现在这是我的尝试:

(define split
    (lambda (L)
        (if
            (null? L)
            '()
            (list (first L) (second L))
        )
    )
)

(define first
    (lambda (L)
        (if
            (null? L)
            '()
            (cond
                (
                    (null? (cdr L)) 
                    (car L)
                )
                (
                    #t 
                    (cons
                        (car L)
                        (first (cdr (cdr L)))
                    )
                )
            )
        )
    )
)

(define second
    (lambda (L)
        (if
            (null? L)
            '()
        )
        (cond
            (
                (null? (cdr L))
                '()
            )
            (cons
                (car (cdr L))
                (second (cdr (cdr L)))
            )
        )
    )
)

但不是我得到的预期结果:

对于(split '(1234)),我得到((1234)())
对于(first '(1234)),我得到(1234)
对于(second '(1234)),我得到()

2 个答案:

答案 0 :(得分:5)

需要考虑的一些事项:

  • 您有括号问题
  • cond的最后一个条件中,您应该使用else
  • 不需要使用if然后使用cond,将所有条件都放在cond中,它会让代码更清晰
  • first中的基本案例有误,您必须返回一个列表
  • split中,您应该使用list来构建返回的列表,而不是cons
  • 你真的,真的应该改进代码的格式 - 括号不应该单独留在一行,它们不像其他编程语言中的{}括号 - 这将改善代码的可读性

考虑到上述情况,这里有一个解决所有问题的实现:

(define split
  (lambda (L)
    (if (null? L)
        '()
        (list (first L) (second L)))))

(define first
  (lambda (L)
    (cond ((null? L) '())
          ((null? (cdr L)) L)
          (else (cons (car L)
                      (first (cdr (cdr L))))))))

(define second
  (lambda (L)
    (cond ((null? L) '())
          ((null? (cdr L)) '())
          (else (cons (car (cdr L))
                      (second (cdr (cdr L))))))))

现在它按预期工作:

(split '(1 2 3 4 5 6 7 8))
=> '((1 3 5 7) (2 4 6 8))

(split '(cat bird dog horse mouse pig tiger gerbil cow))
=> '((cat dog mouse tiger cow) (bird horse pig gerbil))

答案 1 :(得分:2)

我正在看这个并记住Merge Sort implementation from Rosetta Code for PicoLisp。在那里你只需要一个程序就可以同时执行奇数和偶数列表,对于这个问题也是如此。

;; makes a list of every other element
(define (alt lst)
  (if (or (null? lst)
          (null? (cdr lst)))
      lst
      (cons (car lst)
            (alt (cddr lst)))))

;; no safeguard against empty list
;; needs at least one element.
(define (split lst)
  (list (alt lst) (alt (cdr lst))))

(split '(1 2 3 4 5 6 7 8)) 
; ==> ((1 3 5 7) (2 4 6 8))

(split '(cat bird dog horse mouse pig tiger gerbil cow)) 
; ==> ((cat dog mouse tiger cow) (bird horse pig gerbil))

为了使零元素列表的安全性被遗漏为练习。