【发布时间】:2008-09-20 13:36:52
【问题描述】:
给定一个列表,我将如何选择一个包含原始列表切片的新列表(给定偏移量和元素数量)?
编辑:
到目前为止的好建议。 SRFI 中没有指定内容吗?这似乎是一个非常基本的事情,所以我很惊讶我需要在用户空间中实现它。
【问题讨论】:
-
我只是想为 Nathan Sanders 的回答提出我的建议,这绝对是比其他提交的更好地使用 SRFI。此外,那将是我写的答案。 :-)
给定一个列表,我将如何选择一个包含原始列表切片的新列表(给定偏移量和元素数量)?
到目前为止的好建议。 SRFI 中没有指定内容吗?这似乎是一个非常基本的事情,所以我很惊讶我需要在用户空间中实现它。
【问题讨论】:
奇怪的是,slice 没有随 SRFI-1 提供,但您可以使用 SRFI-1 的 take and drop 使其更短:
(define (slice l offset n)
(take (drop l offset) n))
我认为我与 Scheme 一起使用的其中一个扩展,如 PLT Scheme 库或 Swindle,会内置此功能,但似乎并非如此。它甚至没有在新的 R6RS 库中定义。
【讨论】:
(slice '(1 2 3 4 5 6 7 8 9 0) 3 9),因为它会用完列表。实际上,您必须向它传递一个从开始的偏移量和最终列表的长度,而不是从零开始的两个偏移量。您也不能这样做 (slice l 3 -4) (python 用户期望的意思是“从列表 l 的第三个到倒数第四个元素获取所有内容”)。真正的切片函数会复杂得多。
下面的代码会做你想做的事:
(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)
>
【讨论】:
你可以试试这个功能:
subseq 序列开始&可选结束
start 参数是您的偏移量。 end 参数可以通过简单地添加 start + number-of-elements 轻松转换为要抓取的元素数。
一个小小的好处是 subseq 适用于所有序列,这不仅包括列表,还包括字符串和向量。
编辑:似乎并非所有 lisp 实现都有 subseq,但如果你有它,它会很好地完成工作。
【讨论】:
(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 '())))
【讨论】:
这是我使用正确尾调用的slice 实现
(define (slice a b xs (ys null))
(cond ((> a 0) (slice (- a 1) b (cdr xs) ys))
((> b 0) (slice a (- b 1) (cdr xs) (cons (car xs) ys)))
(else (reverse ys))))
(slice 0 3 '(A B C D E F G)) ;=> '(A B C)
(slice 2 4 '(A B C D E F G)) ;=> '(C D E F)
【讨论】:
试试这样的:
(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)))
'()))))
【讨论】: