从列表 Racket 中获取 n 个元素

fetch n-elements from a list Racket

如何从列表中获取 n 个元素, 我知道 first、rest 等,但是如果我想要列表中的前 3 个元素怎么办,

I.E (get-first 3 (list 1 2 3 4 5 6)) -> (list 1 2 3)

(get-first 5 (list 54 33 2 12 11 2 1 22 3 44)) -> (list 54 33 2 12 11)

这不是家庭作业,但这段代码将帮助我完成任务的大局,我真的被困住了,只需要一些提示。 我不允许使用 Lambda 或 build-list 并且没有递归,我需要以某种方式仅使用 map、filter、foldr 等来做到这一点...

正如@AlexisKing 所提到的,您可以简单地使用 Racket 中 built-in 的 take 过程:

(take '(1 2 3 4 5 6) 3)
=> '(1 2 3)

(take '(54 33 2 12 11 2 1 22 3 44) 5)
=> '(54 33 2 12 11)

如果出于某种原因不允许您仍然可以使用 higher-order 过程推出您自己的版本并且没有显式递归,但是 do 注意不要使用 lambda是不可能的,你说的允许的程序(map,filter,foldr)都收到一个lambda作为参数,无论如何,Scheme 中的 所有 过程都是 lambda 的底层。

这是一个人为的解决方案,传递一个累加器,该累加器在遍历输入列表时记住我们在哪个索引中,并在 cdr 部分构建输出列表。如果不使用 lambda 就无法完成,但是如果您在那里看到它感到困扰,请将其提取到辅助程序并传递给它:

(define (get-first n lst)
  (reverse
   (cdr
    (foldr (lambda (e acc)
             (if (= (car acc) n)
                 acc
                 (cons (add1 (car acc))
                       (cons e (cdr acc)))))
           '(0 . ())
           (reverse lst)))))

它仍然按预期工作,但是当 built-in 程序会做同样的事情时,不要做这么复杂的事情:

(get-first 3 '(1 2 3 4 5 6))
=> '(1 2 3)

(get-first 5 '(54 33 2 12 11 2 1 22 3 44))
=> '(54 33 2 12 11)