在常见的lisp中找到字符频率

时间:2011-11-05 01:33:20

标签: lisp common-lisp

例如,如果我输入字符序列

“Hello world”H = 1 e = 1 l = 3 o - 2 r = 1 w = 1 d = 1

可以帮助我一些人

我在网上找到了这个code,但我不明白它我想要一个更简单的

(defun letter-freq (file)
 (with-open-file (stream file)
  (let ((str (make-string (file-length stream)))
        (arr (make-array 256 :element-type 'integer :initial-element 0)))
    (read-sequence str stream)
    (loop for c across str do (incf (aref arr (char-code c))))
    (loop for c from 32 to 126 for i from 1 do
      (format t "~c: ~d~a"
        (code-char c) (aref arr c)
        (if (zerop (rem i 8)) #\newline #\tab))))))

(letter-freq "test.lisp")

4 个答案:

答案 0 :(得分:4)

以上代码非常特定于ASCII字符。如果要对任何可能的字符执行相同操作,可以使用哈希表。

(defun letter-freq (file)
  (with-open-file (stream file)
    (let ((str (make-string (file-length stream)))
          (ht (make-hash-table)))
      (read-sequence str stream)
      (loop :for char :across str :do
        (incf (gethash char ht 0)))
      (maphash (lambda (k v)
                 (format t "~@C: ~D~%" k v))
               ht))))

~@C format指令打印charaсter,就像prin1一样。

答案 1 :(得分:2)

我会将任务分成两个较小的任务:

1从文件中读取并返回一个字符串 2计算字符串

中字符的字母频率

对于1,您可以使用文件字符串函数(https://github.com/kugelblitz/young/blob/master/external-helpers.lisp

对于2,您可以使用'bag'数据结构和fset包库(http://common-lisp.net/project/fset/):

(defun letter-freq (str)
  (let ((bg (fset:convert 'fset:bag str)))
    (fset:do-bag-pairs (value mult bg)
                       (format t "~a: ~a~%" value mult))))

答案 2 :(得分:1)

这段代码并不难理解。它打开文件将其读入字符串。同时,它还会生成一个数组来保存结果(大小为256,因为理论上你可以将非打印字符放在128以上,我猜)。然后它遍历数组并递增数组中的相应元素。例如,'a'是32,所以当它找到'a'时,它会增加数组元素32。

最后,它只会覆盖可打印的字符结果并打印出来。

答案 3 :(得分:1)

我倾向于同意drysdam。我有一段时间没有触及任何Common Lisp代码,并且能够像他所描述的那样以一般的理解来阅读这个例子。

我不知道您使用的是哪种Lisp环境,但即使在裸 REPL (读取eval打印循环)中,您也可以向系统询问(describe 'some-unknown-symbol)。如果你碰巧“强迫”使用Emacs它有SLIME y gobful功能。

我今天看到这是你的第二个与lisp相关的问题。也许最好打一些book s。