如何在Scheme

时间:2017-12-10 09:54:45

标签: scheme racket

 我正在努力学习Scheme,我遇到了一个问题。 我能够创建一个递归函数来创建一个像(5,4,3,2,1)这样的列表。但我不知道如何创建一个功能 (让我们说(define (make_list n))) 具有升序的元素(1,2,3,4,5 ...... n)。 有人提示吗?

 (define (make_list n)
  (if (= n 1)
      (list 1)
  (append (list n) (make_list (- n 1)))))

所以这就是我用n元素创建一个列表的方法,然后返回

> (make_list 3)
'(3 2 1)
> (make_list 5)
'(5 4 3 2 1)

我需要的是返回类似的内容:

> (make_list 3)
'(1 2 3)
> (make_list 5)
'(1 2 3 4 5)

6 个答案:

答案 0 :(得分:1)

你应该避免在没有必要的地方使用追加。 追加将元素添加到列表的后面,首先需要遍历整个列表以查找结尾。缺点不需要这样做,它可以立即向前面添加元素。

升序列表和降序列表都可以使用缺点创建。

(define (desc-list n)
   (if (= n 1)
      (list 1)
      (cons n (desc-list (- n 1)))))

> (desc-list 5)
'(5 4 3 2 1)

(define (asc-list from to)
   (if (> from to)
      '()
      (cons from (asc-list (+ from 1) to))))

> (asc-list 1 5)
'(1 2 3 4 5)

虽然如果你真的想要也可以使用追加。 所有你需要做的就是反转你传递给追加的参数。

(define (make_list n)
   (if (= n 1)
      (list 1)
      (append (make_list (- n 1)) (list n))))

> (make_list 5)
'(1 2 3 4 5)

所以你非常接近。

答案 1 :(得分:1)

根据您当前的定义

(make-list 5) = (append (list 5) (make-list 4))
              = { 5 } + { 4 ..... 1 }

但你想要

(make-list 5) = { 1 ..... 4 } + { 5 }
              = (append  ...  ...)

因此,要更改结果的顺序,您只需更改 创建结果的顺序。

答案 2 :(得分:1)

不要使用append一次列出一个元素列表。 append附加两个列表线性时间,因此如果对参数中的每个元素执行此操作,则可以使其成为二次时间。

列表是cons - 从头到尾。如果你想列出0..n你需要在积累时向下计数,如下所示:

(define (make-list n)
  (define (helper n acc)
    (if (< n 0)
        acc
        (helper (- n 1) (cons n acc))))
  (helper n '()))

有时你不能这样做,然后你通常会先反向制作清单,然后反过来。这是两个线性时间操作,使最终结果也是线性的:

(define (sum lst1 lst2)
  (let helper ((lst1 lst1) (lst2 lst2) (acc '()))
    (if (null? lst1)
        (reverse acc)
        (helper (cdr lst1) 
                (cdr lst2)
                (cons (+ (car lst1) (car lst2)) acc)))))

答案 3 :(得分:1)

只是在这个帖子中添加srfi-1包含iota function

; (iota numElems [start] [step])

> (iota 10)
(0 1 2 3 4 5 6 7 8 9)
> (iota 10 0 2)
(0 2 4 6 8 10 12 14 16 18)
> (iota 10 10 1)
(10 11 12 13 14 15 16 17 18 19)

答案 4 :(得分:1)

您可以使用range函数列出升序元素:

> (range 1 20)
'(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

如果您想迭代此列表,请考虑使用in-range代替,这将根据需要生成列表项,例如:

> (in-range 1 20)
#<stream>
> (for ([i (in-range 1 20)])
       (displayln (* i 10)))
10
20
30
...

但通常情况下mapfilterfold都是处理迭代的更好方法。

阅读此处的文档: https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Flist..rkt%29._range%29%29

答案 5 :(得分:0)

考虑使用子程序。您可以使用您的代码作为子过程,只需api/books/1?genre=Fiction&status=Available主过程中的结果:

reverse

或者,更有效率,您可以使用累加器(在此示例中称为(define (make-list n) (define (sub n) (if (= n 1) (list 1) (append (list n) (sub (- n 1))))) (reverse (sub n))) );它使用res而不是cons,并且不需要额外的append步骤:

reverse