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?
<代码>等式?
有一些令人惊讶的失败案例。