【问题标题】:How do I take a slice of a list (A sublist) in scheme?如何在方案中获取列表的一部分(A 子列表)?
【发布时间】:2008-09-20 13:36:52
【问题描述】:

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

编辑:

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

【问题讨论】:

  • 我只是想为 Nathan Sanders 的回答提出我的建议,这绝对是比其他提交的更好地使用 SRFI。此外,那将是我写的答案。 :-)

标签: lisp scheme


【解决方案1】:

奇怪的是,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 的第三个到倒数第四个元素获取所有内容”)。真正的切片函数会复杂得多。
  • 你在想Python slice,它使用了offset1,offset2。对于偏移量、元素数量的方法,这是正确的答案:如果列表用完,“从第 3 个开始取 9 个元素”应该给你少于 9 个。 (我个人认为 Python 的方法更好,但这不是问题所在。)
【解决方案2】:

下面的代码会做你想做的事:

(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)
> 

【讨论】:

  • get-n-items 中有一个错字 - if-form 的 else 部分需要引用。你能编辑一下吗?
【解决方案3】:

你可以试试这个功能:

subseq 序列开始&可选结束

start 参数是您的偏移量。 end 参数可以通过简单地添加 start + number-of-elements 轻松转换为要抓取的元素数。

一个小小的好处是 subseq 适用于所有序列,这不仅包括列表,还包括字符串和向量。

编辑:似乎并非所有 lisp 实现都有 subseq,但如果你有它,它会很好地完成工作。

【讨论】:

  • subseq 是 CL 函数吗?至少它似乎不是 PLT-Scheme 的一部分。
  • Gauche 有它:practical-scheme.net/wiliki/arcxref?subseq。不知道其他人。
  • 很奇怪。我读到了人工智能范式,它是作为标准的一部分提出的。我想我不确定是哪一种标准。 :P 抱歉。
【解决方案4】:
(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 '())))

【讨论】:

    【解决方案5】:

    这是我使用正确尾调用的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)
    

    【讨论】:

      【解决方案6】:

      试试这样的:

          (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)))
                      '()))))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多