假设我有一个字符串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-search
和C-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)))