【问题标题】:Emacs regexp count occurrencesEmacs 正则表达式计数出现次数
【发布时间】:2012-08-04 13:28:18
【问题描述】:

我正在寻找 最快 例程(非交互式)来获取字符串中正则表达式的匹配数。

类似

(count-occurrences "a" "alabama")
=> 4

【问题讨论】:

    标签: regex emacs


    【解决方案1】:

    我可能会这样做:

    (defun count-occurrences (regexp string)
      "Return the number of occurrences of REGEXP in STRING."
      (let ((count 0))
        (with-temp-buffer
          (save-excursion (insert string))
          (while (re-search-forward regexp nil t)
            (cl-incf count)))
        count))
    

    【讨论】:

    • ...测试表明 event_jr 和 cjohansson 的答案更快。我最初认为不同之处可能是(insert string),但实际上re-search-forward 似乎比使用string-match 慢得多(至少相对而言),这让我感到惊讶。不过,我的测试非常粗略,因此不同的输入可能会产生不同的结果。
    【解决方案2】:

    这里是一个不使用栈的emacs-lisp函数

    (defun count-occurences-in-string (pattern string)
      "Count occurences of PATTERN in STRING."
      (let ((occurences 0)
            (start 0)
            (length (length string)))
        (while (and
                (< start length)
                (string-match pattern string start))
          (setq occurences (1+ occurences))
          (setq start (match-end 0)))
        occurences))
    

    【讨论】:

      【解决方案3】:

      如果创建变量副本没有任何问题,可以尝试

      (- (length (split-string "Hello World" "o")) 1)
      (- (length (split-string "aaabaaa" "a")) 1)
      (- (length (split-string "This
      string
      has three
      newlines" "
      ")) 1)
      
      2
      6
      3
      

      如果你加载cl-lib包没有问题,那么你可以试试

      (require 'cl-lib)
      
      (cl-count ?o "Hello World")
      (cl-count ?a "aaabaaa")
      (cl-count ?
       "This
      string
      has three
      newlines")
      
      2
      6
      3
      

      【讨论】:

        【解决方案4】:

        在包s中,有函数s-count-matches

        【讨论】:

          【解决方案5】:

          这是使用递归和累加器的更实用的答案。作为一个额外的好处,它不使用cl

          (defun count-occurences (regex string)
            (recursive-count regex string 0))
          
          (defun recursive-count (regex string start)
            (if (string-match regex string start)
                (+ 1 (recursive-count regex string (match-end 0)))
              0))
          

          【讨论】:

          • 这可能看起来和感觉更优雅,但是如果没有尾调用优化,递归解决方案会受到堆栈大小的限制。由于堆栈维护,它也会变慢。
          • 非常正确。我在想它在 Haskell 中的完成方式。使用这种方法,我最多可以计算 197 次。
          • @event_jr 你知道有什么办法可以绕过这个问题吗?
          • 并非如此。 Emacs-lisp 只是不适合递归解决方案。我倾向于将 Emacs-lisp 视为具有一流功能的程序,而不是真正的功能。
          • 我写了一个尾调用优化版:(defun count-occurences (regex string) (recursive-count regex string 0 0)) (defun recursive-count (regex string start counter) (if (string-match regex string start) (recursive-count regex string (match-end 0) (+ counter 1)) counter))
          【解决方案6】:

          how-many(别名为count-matches)这样做,但适用于缓冲区。

          这是一种适用于字符串的方法:

          (defun how-many-str (regexp str)
            (loop with start = 0
                  for count from 0
                  while (string-match regexp str start)
                  do (setq start (match-end 0))
                  finally return count))
          

          【讨论】:

          • loop 是一个宏,完全编译,没有问题。
          • 在我的(初步)测试中,这是最快的答案,而接受的答案是最慢的。
          【解决方案7】:

          count-matches 以交互方式进行。也许是一个开始寻找的好地方。

          【讨论】:

          • 是的,它使用搜索转发,witch 也是面向交互的……我知道我要做什么;我要去谷歌搜索“如何在 elisp 中对单个 defun 进行基准测试”。
          猜你喜欢
          • 1970-01-01
          • 2015-04-17
          • 1970-01-01
          • 2021-01-23
          • 2021-12-31
          • 2017-05-25
          • 2013-09-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多