如何在Emacs Lisp中计算字符串中特定字符的数量



假设我有一个字符串s.

这个字符串s可能包含以下内容:

asdf-asdfasdfasf-fasdf-asdfasdfasdf

或者这个:

asf-asdfaf

还有这个:

aasdaf

如何使用Emacs Lisp计算这个字符串中的破折号(-(,并将这个数字存储在一些变量中,例如破折号计数?

应该由以下函数来完成:

(defun count-chars (char str)
(let ((s (char-to-string char))
(count 0)
(start-pos -1))
(while (setq start-pos (string-search s str (+ 1 start-pos)))
(setq count (+ 1 count)))
count))

你这样称呼它:

(count-chars ?- "---") ==> 3
(count-chars ?- "foo-bar") ==> 1
(count-chars ?- "-foo-bar-baz") ==> 3
(count-chars ?- "foobarbaz") ==> 0

要将变量设置为找到的数字,只需使用setq:

(setq count-of-chars (count-chars ?- "foo-bar-baz"))

基本上,我们循环寻找第一个破折号:如果我们找到了它,我们就会记得在哪里,这样我们下次就可以开始在循环中寻找它右边的地方。循环体只计算我们看到的每一个。当我们找不到更多时,string-search(和setq(返回nil,循环退出,然后我们返回累积的count。有关详细信息,请参见函数string-searchC-h f string-search的文档字符串。

另一种方法更类似于python的split字符串方法:split-string将分隔符上的字符串拆分为一个部分列表。然后,我们计算部分(列表的长度(并减去1:"a-b-c"被拆分为("a" "b" "c"),因此有三个部分,但只有两个分隔符。

(defun count-chars (char str)
(let ((s (char-to-string char)))
(- (length (split-string str s)) 1)))

同样,有关所有详细信息,请参阅split-string(C-h f split-string(的文档字符串。

在这两种情况下,我们都将字符变元转换为字符串变元,因为第一种情况下的string-search和第二种情况中的split-string都需要字符串变元(在第一种情况中搜索,在第二种情形中用作分隔符-事实上,split-string可以使用正则表达式作为分隔符(。在Emacs Lisp中,字符和字符串是不同的数据类型,因此如果您真的想要将字符作为count-chars的第一个参数,则转换是必要的。但你可以把它变成一个字符串:

(defun count-seps (sep str)
(- (length (split-string str sep)) 1))

然后你会这样称呼它:

(count-seps "-" "abc-def-ghi-")

哪个更简单更通用:

(count-seps "-;-" "abc-;-def") ==> 1

但是您必须担心分隔符字符串中的特殊字符:

(count-seps "-*-" "abcd-------def") ==> 1

因为正则表达式CCD_ 18匹配一个或多个短划线,所以它匹配所有七个短划线:只有一个分隔符。这是否是你想要的是有争议的。如果你不想要它,你需要转义分隔符字符串中的特殊字符:

(defun count-chars (sep str)
(let ((qsep (regexp-quote sep)))
(- (length (split-string str qsep)) 1)))

最新更新