文字の出現頻度を調べる

文字の出現頻度を調べる

それっぽい手続きはなさそうなので,自力で数えることにする.

(use gauche.collection)
(define (match-count re str)
  (define (grp-to-assoc grp)
    (if (null? grp)
	'()
	(cons (cons (caar grp) (length (car grp))) (grp-to-assoc (cdr grp)))))
  (let1 grp (group-collection (scan-match-string re str) :test string=?)
    (grp-to-assoc grp)))

(match-count #/[うえ]/ "あああいいううええお")
  =>(("う" . 2) ("え" . 2))
(match-count #/./ "3.14159265357919")
  =>(("3" . 2) ("." . 1) ("1" . 3) ("4" . 1) ("5" . 3) ("9" . 3) ("2" . 1) ("6" . 1) ("7" . 1))

これだけだと何だか分からんですね...分解して動作を見ます.

group-collectionでのグループ化

gauche.collectionにあるgroup-collectionを使うと,グループ化が簡単にできます.
collにグループ化したいコレクションを指定します.

(use gauche.collection)
(group-collection coll &keyword key test)

以下がグループ化の例.
"う"もしくは"え"にマッチした結果をグループ化してリストにしています.:testは等価性判定のオプションで,ここではstring=?(文字列としての等価)を指定します.デフォルトはeqv?で,オプションを指定しないと意図しない結果になってしまうため要注意.

(let ((re #/[うえ]/)
      (str "あいうえおあいうえお"))
  (group-collection (scan-match-string re str) :test string=?))
  =>(("う" "う") ("え" "え"))
グループを連想リストへ

グループ化ができてしまえば,あとは連想リストにするだけです.

(define (grp-to-assoc grp)
  (if (null? grp)
      '()
      (cons (cons (caar grp) (length (car grp))) (grp-to-assoc (cdr grp)))))

(grp-to-assoc '(("あ" "あ" "あ") ("い" "い") ("う")))
 =>(("あ" . 3) ("い" . 2) ("う" . 1))