与球拍拆分列表

时间:2014-09-14 21:49:41

标签: racket

给定一个列表和一个数字n,我试图将一个列表分成两个单独的列表:一个列入长度为n的列表,第二个列表是原始列表的其余列表。

这就是我所拥有的:

(define (part lst i)
(if (> i 0)
(list (append (list (first lst)) (list (part (rest lst) (- i 1)))))
(append lst)))

其中lst是输入的列表,i是数字。当我用数字2输入列表'(1 2 3 4)时,我返回一个输出:'((1((2(3 4)))))而不是我想要的'((1 2) )(3 4))。

这是一个家庭作业,所以如果有人可以指出我的问题所在的正确方向,并且因为这是一个新的任务,我将非常感激,我只能被允许使用简单的球拍功能

编辑:

当我将代码更改为:

(define (part lst i)
(if (> i 0)
(append (list (first lst)) (list (part (rest lst) (- i 1))))
(append lst)))

我输出'(1(2(3 4)))。

1 个答案:

答案 0 :(得分:3)

使用现有库

在Racket中有一种简单的方法可以解决这个问题,只需使用内置的split-at过程(也可以在SRFI-1库中找到)。这样做的好处是可以在输入列表中进行单次传递:

(define (part lst i)
  (let-values (((head tail) (split-at lst i)))
    (list head tail)))

另一种选择是使用Racket的内置程序takedrop(也可在SRFI-1中使用) - 但这会在输入列表中进行两次传递:

(define (part lst i)
  (list (take lst i)
        (drop lst i)))

从头开始实施

要构建我们自己的解决方案,我们可以编写一个单行程的过程,如下所示:

(define (part lst i)
  (if (negative? i)
      (error "index can't be negative")
      (let loop ((lst lst) (acc '()) (i i))
        (cond ((and (empty? lst) (positive? i))
               (error "index is too large for list"))
              ((zero? i)
               (list (reverse acc) lst))
              (else
               (loop (rest lst) (cons (first lst) acc) (sub1 i)))))))

此外,我们可以实现我们自己的takedrop版本 - 再次,这将遍历输入列表两次:

(define (my-take lst i)
  (if (> i 0)
      (cons (first lst)
            (my-take (rest lst) (- i 1)))
      '()))

(define (my-drop lst i)
  (if (> i 0)
      (my-drop (rest lst) (- i 1))
      lst))

(define (part lst i)
  (list (my-take lst i)
        (my-drop lst i)))