结构定义:
(define-struct movie (title genre stars))
;; title is a nonempty string
;; genre is a nonempty string
;; stars us a list of nonempty strings
我正在尝试编写一个消耗电影列表的方案函数,并生成最常出现的类型。
到目前为止,我有以下内容:
(define (popular-gnere movies)
(local
[(define acc movies genre)
(cond
[(empty? movies) genre]
[(equal? genre (movie-genre (first movies)))
(acc (rest movies genre)))
我很难理解如何计算特定类型在特定电影列表中出现的次数。 我知道在这种情况下累积的递归效率最高,但是在完成累加器时遇到了麻烦。
答案 0 :(得分:0)
为什么不修复括号问题并正确缩进代码。按 CRTL + i 。如果标识错误,您可能缺少括号。按运行进行评估,您将收到正确的错误消息。如果您的某些内容不会产生错误,请更新此问题。
您的问题的答案是您向本地程序添加的参数多于全局。这样你就可以获得一个参数,当你在当前的element.eg中找到search元素时,该参数可以保存你增加的计数。
(define (length lst)
(define (length-aux lst cnt)
(if (null? lst)
cnt
(length-aux (cdr lst) (add1 cnt))))
(length-aux lst 0))
或更好的名为let
(define (length lst)
(let length-aux ((lst lst) (cnt 0))
(if (null? lst)
cnt
(length-aux (cdr lst) (add1 cnt)))))
修改强>
我建议至少有4个辅助程序来解决每个问题。 (如果您使用球拍自己的remove
,count
和argmax
,则会减少。请注意,可能还有很多其他方法可以解决这个问题,但这就是我在没有哈希表的情况下解决它的方法。
由于你只对流派感兴趣,首先想象的是你可以做(map movie-genre lst)
,这样你就可以获得一个在你的主助手中使用的流派列表。
在你的主助手中,你可以建立一个具有流派和数量的缺点列表。为此,您使用count
的帮助(count 'c '(a b c d c c a) 0) ==> 3
,您只需获取第一个类型并将列表作为第一个累计值计算,然后处理(remove 'c '(a b c d c c a) '()) ==> (a d b a)
的结果。的清单。
处理完毕后,您在累加器((a . 4) (b . 6) ...)
中就有了帮助(max-genre 'a 4 '((b . 6) (c . 20) (d . 10))) ; ==> c
主助手看起来像这样:
(define (aux lst acc)
(if (null? lst)
(max-genre (caar acc) (cdar acc) (cdr acc))
(aux (remove (car lst) lst '())
(cons (cons (car lst) (count (car lst) lst 0)) acc))))
现在你可以通过一次hash table更简单地做到这一点。在阅读完所有元素后,您仍然需要max-genre
/ argmax
。
答案 1 :(得分:0)
首先,您需要确定键值数据类型。您可以使用关联列表,但哈希表是更有效的选择。
让我们从一个简短的清单开始:
(define-struct movie (title genre stars))
(define films
(list
(make-movie "Godfater" "Crime" '("Marlon Brando" "Al Pacino"))
(make-movie "Rambo" "Thriller" '("Sylvester Stallone"))
(make-movie "Silence of the Lambs" "Crime" '("Jodie Foster" "Anthony Hopkins"))))
并创建一个空哈希表
(define h (make-hash))
现在我们处理每部电影,随时更新哈希表:
> (for-each (lambda (e) (hash-update! h e add1 0)) (map movie-genre films))
> h
'#hash(("Thriller" . 1) ("Crime" . 2))
现在我们需要找到最高的数量:
> (hash-values h)
'(1 2)
> (define most (foldl (lambda (e r) (if (> e r) e r)) 0 (hash-values h)))
> most
2
所以2是我们最高的数。现在我们创建一个包含计数2的所有类型的列表:
> (hash->list h)
'(("Thriller" . 1) ("Crime" . 2))
> (foldl
(lambda (e r) (if (= (cdr e) most) (cons (car e) r) r))
null
(hash->list h))
'("Crime")
全部放在一起:
(define (count-by-genre lst)
(define h (make-hash))
(for-each (lambda (e) (hash-update! h e add1 0)) (map movie-genre lst))
(define most (foldl (lambda (e r) (if (> e r) e r)) 0 (hash-values h)))
(foldl
(lambda (e r) (if (= (cdr e) most) (cons (car e) r) r))
null
(hash->list h)))
但由于以下几个原因,这是非常低效的:
foldl
只是为了找到最高值,而我们可以在更新哈希表时记下它hash->list
创建完整列表(foldl
)和最终结果列表。很多东西和东西。使用特定于Racket的for
构造的另一种更高效的版本可能是:
(define (count-by-genre lst)
(define h (make-hash))
(define most
(for/fold ((highest 0)) ((e (in-list (map movie-genre lst))))
(define new (add1 (hash-ref h e 0)))
(hash-set! h e new)
(max highest new)))
(for/fold ((res null)) (((k v) (in-hash h)))
(if (= v most) (cons k res) res)))