给定一个列表和一个数字 n,我尝试将一个列表拆分为两个单独的列表:一个列表为长度为 n 的列表,第二个列表是原始列表的其余部分。
这是我所拥有的:
(define (part lst i)
(if (> i 0)
(list (append (list (first lst)) (list (part (rest lst) (- i 1)))))
(append lst)))
Run Code Online (Sandbox Code Playgroud)
其中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)))
Run Code Online (Sandbox Code Playgroud)
我得到的输出为 '(1 (2 (3 4)))。
使用现有的库
在 Racket 中有一个简单的方法可以解决这个问题,只需使用内置过程( SRFI-1split-at库中也提供)。这样做的优点是可以一次性遍历输入列表:
(define (part lst i)
(let-values (((head tail) (split-at lst i)))
(list head tail)))
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用 Racket 的内置过程take和drop(也可在 SRFI-1 中使用) - 但这将在输入列表中进行两次传递:
(define (part lst i)
(list (take lst i)
(drop lst i)))
Run Code Online (Sandbox Code Playgroud)
从头开始实施
为了构建我们自己的解决方案,我们可以编写一个进行单遍的过程,如下所示:
(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)))))))
Run Code Online (Sandbox Code Playgroud)
take另外,我们可以实现我们自己的and版本drop- 同样,这将遍历输入列表两次:
(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)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9738 次 |
| 最近记录: |