Racket中列表的长度

5

我试图找出如何获取列表的长度

但是没有成功

显示

 expected: number?
  given: #<procedure:list>
  argument position: 1st
  other arguments...:

我的代码:

(define (length len)

  (list '(1 2 3 4 5 6 7))
  (if (= list null)
     (len)
     (cdr list)
     )
  (+ len 1)
  (length)
  )


(length 0)

我原本的意图是:
  1. 获取列表(由于无法弄清如何获取列表...而在其中)
  2. 创建“if”函数,以便在(cdr list)变为空时可以printf len
如果你们发现任何错误,请告诉我。
我大约两周前尝试学习Racket,但无法弄清如何做到这一点...
谢谢!
3个回答

5
这里是我系统化制作一个用于查找列表长度的函数的方法。
最终结果将会是:
;; length : [Listof Element] -> Number
;; Produces the number of elements in the list

(define (length lst)
  (cond
    [(empty? lst)  0]
    [(cons? lst)   (+ 1 (length (rest lst)))]))

但更重要的是系统性的过程,你可以使用它来编写更多的程序。我在这里使用的过程是书籍 How to Design Programs 中解释的 设计配方

1:什么是列表?

列表要么是空的,要么是第一个元素与其余元素的组合。这个“剩余”是另一个列表。

在Racket中,“空”写作'(),列表的“组合”写作cons

A [Listof Element] is one of:
 - '()
 - (cons Element [Listof Element])

一些列表的示例:
'()                                              ; empty
(cons "I'm alone" '())                           ; one element "I'm alone"
(cons "Hello" (cons "there" '()))                ; two elements "Hello" and "there"
(cons 1 (cons 3 (cons 5 (cons 7 (cons 9 '()))))) ;  five elements, odd numbers

2:什么是length函数?

length函数接受一个列表,并生成一个代表列表中元素数量的数字。空列表的长度为0,上面的示例应该具有长度0125

;; length : [Listof Element] -> Number
;; Produces the number of elements in the list

;; (length '())                                     = 0
;; (length (cons "I'm alone" '()))                  = 1
;; (length (cons "Hello" (cons "there" '())))       = 2
;; (cons 1 (cons 3 (cons 5 (cons 7 (cons 9 '()))))) = 5

(define (length lst)
  ???)

3:定义中的案例是什么?

列表要么为空,要么是cons。为了测试它是否为空,我们可以使用一个cond,其中问题(empty? lst)用于空情况,而问题(cons? lst)用于cons情况。

(define (length lst)
  (cond
    [(empty? lst)  ???]
    [(cons? lst)   ???]))

4:每种情况下有哪些数据的"子部分"可用?

一个空列表没有任何子部分。

然而,(cons Element [Listof Element])有两个子部分:

  • 第一件事,Element
  • 和列表的其余部分,[Listof Element]

在Racket中,您可以使用firstrest来获取它们。

(define (length lst)
  (cond
    [(empty? lst)  ???]
    [(cons? lst)   ... (first lst) ... (rest lst) ...]))

5: 这些子部分中是否有复杂的数据?

(first lst)只是一个Element。就长度而言,它不是复杂的,我们不需要进一步处理它。

(rest lst)是另一个[Listof Element],因此它是复杂的。我们如何处理它?通过使用一个辅助函数。

在这种情况下,我们需要一个与长度相关的辅助函数,并将[Listof Element]作为参数。在这种情况下,该辅助函数恰好是正在定义的函数length!我们可以在(rest lst)上递归使用它,因为它是一个较小的子部分。

(define (length lst)
  (cond
    [(empty? lst)  ???]
    [(cons? lst)   ... (first lst) ... (length (rest lst)) ...]))

6:使用您对长度的直觉和我们之前编写的示例填补空缺

第一个示例 (length '()) = 0 告诉我们第一个 ??? 空缺应该用 0 填充。

(define (length lst)
  (cond
    [(empty? lst)  0]
    [(cons? lst)   ... (first lst) ... (length (rest lst)) ...]))

第二个难点是处理第一个元素和剩余元素的长度。但是你对长度的直觉应该告诉你,合并后的列表的长度应该是剩余部分的长度加一。将其转化为代码如下:
(define (length lst)
  (cond
    [(empty? lst)  0]
    [(cons? lst)   (+ 1 (length (rest lst)))]))

我使用的系统化步骤在书籍如何设计程序中有详细解释。

2

你需要用Scheme思考。如果你已经掌握了一门编程语言,那么在开始阶段并不会对你有帮助。

(define (my-lenght lst)            ; lst is the list argument  
  (if (null? lst)                  ; call function null? to check for empty list
      0                            ; an empty list has zero i length
      (+ 1                         ; length is one more 
          (my-length (cdr lst))))) ; than the list with first element omitted

以下是如何调用该函数的方法:

(my-lenght '(1 2 3)) ; ==> 3

如果你查看你的代码,你调用了 len 作为函数。函数名称只是指向函数对象的变量,因此 + 是一个变量,而 (+ a b) 是一个带有3个变量的代码。其中一个变成了函数,另外两个变成了数字。

0

欢迎来到Lisp,@danny lee!

(define (length-1 lst (acc 0)) 
   (if (null? lst)
       acc
       (length-1 (cdr lst) (+ 1 acc))))

我使用名称length-1,因为Racket原始函数length恰好执行此函数应该执行的操作。(为了不覆盖它,我选择了一个不同的名称)。

啊,你调用的函数是:

(define lst (list 1 3 5 8 7 3))

(length-1 lst)  ;; calls length-1 on lst defined above
;; this returns you the value 6, since this is the length of the list

我强烈推荐你阅读《The little Schemer》这本书——它教你如何递归思考,并提供了所有解决方案,同时也很好地解释了这些解决方案。非常好的一本书!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接