Scheme 编写返回字符串中单词频率的函数
因此,对于我的代码,我需要编写一个函数,返回字符串中单词的频率。 到目前为止,我有以下代码:Scheme 编写返回字符串中单词频率的函数,scheme,racket,Scheme,Racket,因此,对于我的代码,我需要编写一个函数,返回字符串中单词的频率。 到目前为止,我有以下代码: (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)
(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”)
我得到这个错误。
字符串->列表:违反合同
预期:字符串?
给定:(#\i#\space#\t#\e#\r#\e#\space#\p#\e#\r#\s#\o#\n#\space#\i)
我们会感激你的帮助,为什么它会这样做?
我希望我的最终输出看起来像
((hi.2)(there.1)(person.1))错误的原因是
string->list
函数返回了一个字符列表。因此,如果您尝试这样做:
(string->list "hi there person hi")
你最终会得到”(\#h\#i\#space\#t\#h\#e…
而不是”(你好,有人你好)
最简单的方法是通过扫描字符列表并检测当前字符(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))))))))))
(指向lat“hi there person hi”的字符串)
将返回”(hi there person hi)
以下是步骤:
string->list
将字符串转换为字符列表构建列表
,将初始作用域变量绑定到初始值if
表达式,如下所示
- 如果找到空格,则使用不带空格的字符列表调用
,并通过向其追加build list
并将w
重置为空字符串来更新w
l
- 否则,通过在字符串
后追加w
来正常重复(字符串(汽车))
w
是一个单词累加器,每当在s
char列表中发现空格时,它可以帮助构建每个单词并将其转换为符号,并将其放入最终列表中
这样,计算结果列表中每个符号的出现次数应该很简单。我学到的一件事是,您应该在解释器中测试您的假设:
> (string->list "hi")
'(#\h #\i)
string->list
生成字符列表,而不是字符串列表。当您稍后尝试在该字符列表上递归时,此功能将崩溃。
(即使
string->list
生成了字符串列表,递归也会中断,因为函数需要的是字符串,而不是列表。)
Racket有许多有用的库函数,您正在寻找的函数确实存在
string split
将字符串(默认为空白)拆分为字符串列表
> (string-split "hi there hi")
'("hi" "there" "hi")
还有一个groupby
,它将一个列表分组为一个列表列表。(在优秀手册中查找这些功能。)
groupby
需要一些分组依据。让我们使用字符串本身
> (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))
请注意,
string->list
返回的是字符列表,而不是符号列表。因此(string->list“hi”)
返回(#\h#\i)
。您知道如何将字符串直接转换为列表吗?所以它就变成了“(hi-there-person-hi)。您可以拆分字符串并在结果字符串列表上映射字符串->符号,即(映射字符串->符号(字符串拆分“hi there person hi”)
@M.Maric请参见我的答案。这应该很简单。