所以对于我的代码,我需要编写一个函数来返回字符串中单词的频率。 到目前为止,我有以下代码:
(define (num-occurs sym lst)
(define (counter sym lst count)
(cond ((null? lst) count)
((equal? (car lst) sym) (counter sym (cdr lst) (+ 1 count)))
(else (counter sym (cdr lst) count))))
(counter sym lst 0))
(define (remove-all elem lst)
(if (null? lst)
'()
(if (equal? elem (car lst))
(remove-all elem (cdr lst))
(cons (car lst) (remove-all elem (cdr lst))))))
(define (word-frequencies str)
(let ((lst (string->list str)))
(if (null? lst)
'()
(append (list (cons (car lst) (num-occurs (car lst) lst)))
(word-frequencies (remove-all (car lst) (cdr lst)))))))
当我给它一个输入时:(字词频率“hi there person hi”)
我收到此错误。 string-&gt; list:合同违规 预期:字符串? 给出:(#\ i#\ space#\ t#\ e#\ r#\ e#\ space#\ p#\ e#\ r \ n#\ s#\ o#\ n#\ space#\ i)< / p>
帮助将被理解为什么它这样做? 我希望我的最终输出看起来像。
((hi.2)(那里)(人.1))
答案 0 :(得分:1)
我学到的一件事是你应该在翻译中测试你的假设:
> (string->list "hi")
'(#\h #\i)
string->list
生成一个字符列表,而不是字符串列表
当您稍后尝试递归此字符列表时,这会中断
(即使string->list
确实产生了一个字符串列表,递归也会破坏,因为你的函数需要一个字符串,而不是一个列表。)
Racket有许多有用的库函数,而你正在寻找的 存在。
string-split
将字符串(默认情况下为空格)拆分为字符串列表。
> (string-split "hi there hi")
'("hi" "there" "hi")
还有group-by
,它将列表分组到列表中
(在优秀的手册中查找这些功能。)
group-by
需要分组。让我们自己使用字符串。
> (define id (lambda (x) x))
> (group-by id (string-split "hi there hi"))
'(("hi" "hi") ("there"))
这看起来非常有用 我们还可以使用构建单词和频率对的函数:
> (define (frequency-pair strings) (cons (car strings) (length strings)))
> (frequency-pair '("hi" "hi"))
'("hi" . 2)
> (map frequency-pair (group-by id (string-split "hi there hi")))
'(("hi" . 2) ("there" . 1))
把它放在一起:
(define (word-frequencies str)
(define (id x) x) ; Group strings by their own value
(define (frequency-pair strings) (cons (car strings) (length strings)))
(map frequency-pair (group-by id (string-split str))))
> (word-frequencies " hi hello hi there over there")
'(("hi" . 2) ("hello" . 1) ("there" . 2) ("over" . 1))
答案 1 :(得分:0)
错误的原因是因为string->list
函数返回了一个字符列表。所以如果你尝试做这样的事情:
(string->list "hi there person hi")
您最终会使用'(\#h \#i \#space \#t \#h \#e ...)
而不是'(hi there person hi)
。
最简单的方法是通过扫描字符列表来组成字符串中的符号列表,并检测当前字符(car
)何时是#\space
(空白),并构建每个单词基于此的字符串。这可能不是最有效的方式,但它可以完成这项工作。
(define (string-to-lat str)
(let ([char-list (string->list str)])
(let build-list ([s char-list] [l '()] [w ""])
(cond ((null? s) l)
((null? (cdr s))
(append l (list (string->symbol (string-append w (string (car s)))))))
(else
(if (char=? (car s) #\space)
(build-list (cdr s) (append l (list (string->symbol w))) "")
(build-list (cdr s) l (string-append w (string (car s))))))))))
(string-to-lat "hi there person hi")
将返回'(hi there person hi)
。
以下是步骤:
string->list
的字符列表。build-list
,将初始范围变量绑定到初始值。if
表达式,就像这样
build-list
,并通过向其添加l
更新w
,然后重置w
一个空字符串。(string (car s))
附加到字符串w
来正常重复。 w
是一个单词累加器,它可以帮助构建每个单词并将其转换为符号,并在s
字符列表中找到空格时将其放入最终列表中。
通过这种方式,可以直接计算结果列表中每个符号的出现次数。