Scheme 使用`地图'进行球拍计数`
编写一个球拍函数Scheme 使用`地图'进行球拍计数`,scheme,racket,map-function,Scheme,Racket,Map Function,编写一个球拍函数计数出现次数,该函数使用两个符号列表并生成一个符号列表 测量第一个列表中的项目在第二个列表中出现的次数的自然数。例如: (count-occurrences (list 'a 'b 'a 'q) (list 'r 'a 'b 'e 'b 'g)) =>(列表1 2 1 0) 我一直在努力解决这个问题-我如何使用map来实现它,因为对于这个问题,它被指定为我们不能使用递归 我最初的想法是这样做: (define (count-occurrences los1 los2) (
计数出现次数
,该函数使用两个符号列表并生成一个符号列表
测量第一个列表中的项目在第二个列表中出现的次数的自然数。例如:
(count-occurrences (list 'a 'b 'a 'q) (list 'r 'a 'b 'e 'b 'g))
=>(列表1 2 1 0)
我一直在努力解决这个问题-我如何使用map
来实现它,因为对于这个问题,它被指定为我们不能使用递归
我最初的想法是这样做:
(define (count-occurrences los1 los2)
(map
(length (filter (lambda (x) (symbol=? x (first los1))) los2))
los1))
但是在这里使用
length
只能得到数字“a”,而不是递归。对于抽象函数,内部函数只能有一个参数,所以我完全不知道。跟踪键和值的一个好方法是使用哈希表。虽然可以使用map
并传递lambda
写入计数出现次数
,但显式可能更容易看到发生了什么
;;; list list -> list
;;;
(define (count-occurrences keys values)
;; Create data structure
(define ht (make-hash))
;; Initialize data structure with keys
;; Set the value of each key to zero
;; Since we have not started counting
(for ([k keys])
(hash-set! ht k 0))
;; Iterate over values and
;; Increment hash table if
;; When value is a key
(for ([v values])
(if (hash-has-key? ht v)
(hash-set! ht v (+ (hash-ref ht v) 1))
null))
;; Iterate over keys and
;; Create list of values
(for/list ([k keys])
(hash-ref ht k)))
由于禁止递归,显式循环可能比隐式循环更易于维护/可读代码。此外,的变化值得了解。哈希表的优点是重复的键读取相同的值,并且不需要跟踪相同的键两次
使用for
而不是map
的工程优势之一是更容易推断运行时间。此代码的运行时间为2m+n
,其中m
为键
,n
为值
。使用map
的解决方案通常是m*n
。这本身没有什么问题。但这是值得认识的。这是否符合您的要求和限制
(define (count-occurrences lst1 lst2)
(map (lambda (e1)
(count (lambda (e2) (eq? e1 e2))
lst2))
lst1))
如果。。。x…
是一个开放式公式,即引用未绑定变量x
的表达式,将其包装成lambda
形式,使其成为x
中的函数,如下所示:
(lambda (x) ... x ... )
其中,x
受到该lambda形式的约束;这个所谓的lambda函数的一个参数,也就是说,一个由lambda
表单引入的匿名函数
因此,解决问题的方法很简单:认识到这一点
(length
(filter (lambda (x)
(symbol=? x (first los1)))
los2))
实际上应该是
(length
(filter (lambda (x)
(symbol=? x y))
los2))
其中,y
依次表示los1
的每个元素,而不仅仅是第一个元素;然后它是y
中的一个开放式公式,也就是说,y
在那里是无约束的、自由的。所以我们必须抓住它,并使它受到约束,通过。。。是的,将此表达式封装在lambda
形式中,从而使其成为y
中的函数!像这样:
(lambda (y)
(length
(filter (lambda (x)
(symbol=? x y))
los2)))
这就是映射到los1
的内容
通过这个简单的调整,您的代码将成为一个正确的、有效的函数定义。您尝试了什么?请显示您拥有的任何内容。首先编写一个函数,计算符号列表中某个给定符号的出现次数。然后想想如何使用该功能。SRFI-26和SRFI-1几乎是一条直线。您不确定问题的哪一部分?提示:map
的第一个参数应该是一个过程。由于length
产生一个数值结果,(map num lst)
将给您一个map:contract invalition
错误。为什么eq?
而不是equal?
<代码>等式?
有一些令人惊讶的失败案例。