如何在方案中获取列表的一部分(子列表)?

时间:2020-03-06 14:29:03  来源:igfitidea点击:

给定一个列表,我如何选择一个包含原始列表切片的新列表(给出偏移量和元素数量)?

编辑:

到目前为止,很好的建议。 SRFI之一中没有指定任何内容吗?这似乎是一件非常基本的事情,所以令我惊讶的是我需要在用户领域实现它。

解决方案

以下代码将执行我们想要的操作:

(define get-n-items
    (lambda (lst num)
        (if (> num 0)
            (cons (car lst) (get-n-items (cdr lst) (- num 1)))
            '()))) ;'

(define slice
    (lambda (lst start count)
        (if (> start 1)
            (slice (cdr lst) (- start 1) count)
            (get-n-items lst count))))

例子:

> (define l '(2 3 4 5 6 7 8 9)) ;'
()
> l
(2 3 4 5 6 7 8 9)
> (slice l 2 4)
(3 4 5 6)
>

(define (sublist list start number)
  (cond ((> start 0) (sublist (cdr list) (- start 1) number))
        ((> number 0) (cons (car list)
                      (sublist (cdr list) 0 (- number 1))))
        (else '())))

尝试这样的事情:

(define (slice l offset length)
      (if (null? l)
        l
        (if (> offset 0)
            (slice (cdr l) (- offset 1) length)
            (if (> length 0)
                (cons (car l) (slice (cdr l) 0 (- length 1)))
                '()))))

我们可以尝试以下功能:

subseq sequence start &optional end

起始参数是偏移量。只需添加start +元素数,即可将end参数轻松转换为要获取的元素数。

一个小好处是subseq可在所有序列上使用,不仅包括列表,而且包括字符串和向量。

编辑:似乎不是所有的Lisp实现都具有subseq,尽管如果有的话,它将做的很好。

奇怪的是,'slice'并未随SRFI-1一起提供,但是我们可以通过使用SRFI-1的takedrop来使其更短:

(define (slice l offset n)
  (take (drop l offset) n))

我认为我用于Scheme的扩展之一(例如PLT Scheme库或者Swindle)将具有此内置功能,但事实并非如此。在新的R6RS库中甚至没有定义它。