统计一个字母在列表中出现的次数

Count the occurrence of a letter in a list

到目前为止我已经试过了,但我得到了 1:

(define occur
  (lambda (a s)
    (count (curry string-contains? a) s)))

例如:(occur "u" '("u" "uaub" "ubub")) => 1

应该是5

想避免使用咖喱,因为我还不知道它是如何工作的: Dr. Racket Recursion count occurrences

什么是 (string-contains? "abc" "b")

什么是 (string-contains? "b" "abc")

string-contains?的语法是:

(string-contains? haystack needle)

这意味着 你在调用

时使用了错误的参数
(curry string-contains? a)

这里用haystack标识a:要搜索的字符串,不是要搜索的字符串。 curry returns 一个单参数函数,它接受一个 needle 参数,并搜索它是否出现在 a 中。而你想要的是相反的方式。

幸运的是,Racket 为您提供了解决方案:只需将字母 r 添加到 curry 符号:改用 curryr 函数,它绑定最右边的参数,并保留左边的参数免费:

(curryr string-contains? a)

这将使 aneedle 参数(在较大的 haystack 中找到的东西)一致,返回一个接受 haystack 参数的函数。

这个函数就是你应用到列表中每个元素的函数,并计算它returns true 的次数。

currycurryr 对比 cons 函数的说明:

(map (curry cons 'a) '(1 2 3)) -> ((a . 1) (a . 2) (a . 3))
(map (curryr cons 'd) '(1 2 3)) -> ((1 . d) (2 . d) (3 . d))

(curry cons 'a) 有效地为我们提供了函数 (lambda (arg) (cons 'a arg)).

(curryr cons 'd) 有效地为我们提供了函数 (lambda (arg) (cons arg 'd)).

部分应用和柯里化可以可视化为一种糖,可以理解为对显式和更冗长 lambda 语法的转换。如果您对某些柯里化情况感到困惑,这有时会有所帮助。

这会删除字符串连接的 reduce。

(define (how-many items char)
  (define r (regexp (format "[^~a]" char)))
  (string-length (regexp-replace* r (string-join items) "")))

; call it with (how-many '("u" "uaub" "ubub") #\u)

但是,如果您不想一次将所有字符串拼在一起,您可以将各个结果相加。

(define (how-many items char)
  (define r (regexp (format "[^~a]" char)))
  (for/sum ((text (in-list items)))
    (string-length (regexp-replace* r text ""))))

也可以使用以下循环来计算出现次数。它使用 count 函数在从字符串获得的列表中查找匹配项:

(define (occur c l)
  (let loop ((l l)
             (n 0))
    (cond
      [(empty? l) n]
      [else (loop (rest l)
                  (+ n
                     (count (lambda(x) (equal? x c))
                            (string->list (first l)))))])))

请注意,"u" 将作为字符发送。

测试:

(occur #\u '("u" "uaub" "ubub"))

输出:

5