在commonlisp中查找字符频率

在commonlisp中查找字符频率,lisp,common-lisp,Lisp,Common Lisp,例如,如果我输入字符序列 “你好世界”H=1e=1l=3o-2r=1w=1d=1 有人能帮我吗 我在网上找到了这个,但我不明白我想要一个更简单的 (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)

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

“你好世界”H=1e=1l=3o-2r=1w=1d=1

有人能帮我吗

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

(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")

这段代码并不难理解。它打开文件并将其读入字符串。同时,它还制作了一个数组来保存结果(大小为256,因为理论上,我猜非打印字符数可能超过128)。然后它在数组上循环并增加数组中相应的元素。例如,“a”是32,因此当它找到一个“a”时,它会增加数组元素32


最后,它只在可打印的字符结果上循环并打印出来。

我倾向于同意drysdam。我已经有一段时间没有接触过任何常见的Lisp代码了,并且能够像他所描述的那样,以一般的理解来阅读这个示例

我不知道您使用的是哪种Lisp环境,但即使在裸CLREPL(read-eval-print-loop)中,您也可以要求系统
(描述“一些未知符号)
。如果你碰巧“被迫”使用Emacs,它有很多功能


我知道这是你今天第二个与lisp相关的问题。也许最好点击一些s.

上面的代码非常特定于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
格式指令打印字符,就像通过
prin1
我将任务分为两个较小的任务一样:

从文件读取并返回字符串 计算字符串中字符的字母频率

对于,可以使用文件字符串函数()

例如,可以使用“bag”数据结构和fset包库():


是的,我也极力推荐那本书。事实上,我几乎没有做过任何真正的CL编程,我仍然能够理解引用的代码,因为我读过那本书。你读取文件的方法不好,特别是如果你的文件可以有非ascii字符。文件长度以字节为单位返回长度,但字符可以是一个或多个字节。[已编辑的示例代码格式不正确]最好只循环阅读这行代码。我同意,但我只是使用了原始代码中的方法,没有对其进行太多更改。在这里可以找到更好的:@angus:至少字符串永远不会太短,我相信它会有一个错误的上限。将它与fill-=指针(我认为这些指针是由读取顺序自动设置的)结合起来,“所有”您所做的可能都是在浪费RAM。@Vatine:不,填充指针不是由读取顺序自动处理的。在字符串的末尾会有垃圾字符,然后会错误地计算垃圾字符的频率。@angus READ-SEQUENCE返回上次更新的位置,因此可以设置填充指针(或限制循环)。
(defun letter-freq (str)
  (let ((bg (fset:convert 'fset:bag str)))
    (fset:do-bag-pairs (value mult bg)
                       (format t "~a: ~a~%" value mult))))