简体   繁体   English

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

[英]How do I count the number of specific characters in a string in Emacs Lisp?

Let's say I have a string s.假设我有一个字符串 s。

And this string s could contain this:这个字符串 s 可以包含这个:

asdf-asdfasdfasf-fasdf-asdfasdfasdf

or this:或这个:

asf-asdfaf

but also this:还有这个:

aasdaf

How do I count the number of dashes (-) in this string using Emacs Lisp and store this number in some variable eg count-of-dashes?如何使用 Emacs Lisp 计算此字符串中的破折号 (-) 的数量,并将此数字存储在某个变量中,例如破折号计数?

The following function should do it:以下 function 应该这样做:

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

You call it like this:你这样称呼它:

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

To set a variable to the number found, you just use setq :要将变量设置为找到的数字,只需使用setq

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

Basically, we loop looking for the first dash: if we find it we remember where so that we start looking at the place just to the right of it the next time around the loop.基本上,我们循环寻找第一个破折号:如果找到它,我们会记住在哪里,以便我们在下一次循环时开始查看它右侧的位置。 The loop body then just counts every one we see.然后循环体只计算我们看到的每一个。 When we can't find any more, string-search (and the setq ) returns nil and the loop exits, whereupon we return the accumulated count .当我们找不到更多时, string-search (和setq )返回nil并且循环退出,然后我们返回累积的count See the doc string of the function string-search with Ch f string-search for the details.有关详细信息,请参阅 function string-searchCh f string-search的文档字符串。

Another method is more akin to the split string method of python: split-string splits a string on a separator into a list of parts.另一种方法更类似于 python 的split字符串方法: split-string将分隔符上的字符串拆分为部分列表。 We then count the parts (the length of the list) and subtract 1: "abc" is split into ("a" "b" "c") so there are three parts but only two separators.然后我们计算部分(列表的长度)并减去 1: "abc"被拆分为("a" "b" "c") ,所以有三个部分,但只有两个分隔符。

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

Again, see the doc string of split-string ( Ch f split-string ) for all the details.再次,请参阅split-string ( Ch f split-string ) 的文档字符串以了解所有详细信息。

In both cases, we converted the character argument to a string argument, because both string-search in the first case and split-string in the second expect a string argument (to search for in the first case and to use as a separator in the second case - in fact, split-string can use a regular expression as a separator).在这两种情况下,我们都将字符参数转换为字符串参数,因为第一种情况下的string-search和第二种情况下的split-string都需要一个字符串参数(在第一种情况下搜索并用作分隔符第二种情况——实际上, split-string可以使用正则表达式作为分隔符)。 Characters and strings are different data types in Emacs Lisp, so the conversion is necessary if you really want a character s the first argument of count-chars .字符和字符串在 Emacs Lisp 中是不同的数据类型,所以如果你真的想要一个字符作为count-chars的第一个参数,那么转换是必要的。 But you could make it a string instead:但是你可以把它变成一个字符串:

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

and then you would call it like this instead:然后你会这样称呼它:

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

which is simpler and more general:这更简单更通用:

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

but you do have to worry about special characters in the separator string:但是您必须担心分隔符字符串中的特殊字符:

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

since the regular expression -*- matches one or more dashes so it matches all seven dashes: there is only one separator.因为正则表达式-*-匹配一个或多个破折号,所以它匹配所有七个破折号:只有一个分隔符。 Whether that's what you want is debatable.这是否是你想要的还有待商榷。 If you don't want it, you'd need to escape the special characters in the separator string:如果您不想要它,则需要转义分隔符字符串中的特殊字符:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM