【问题标题】:elisp implementation of the "uniq -c" Unix command to count unique lines“uniq -c” Unix 命令的 elisp 实现以计算唯一行
【发布时间】:2017-12-05 17:32:25
【问题描述】:

如果区域中有数据:

花 公园 花 结石 花 结石 结石 花

M-x some-command 应该在不同的缓冲区中给我:

4朵花 2石头 1 个公园

然后可以按频率或项目对这些数据进行排序。

【问题讨论】:

  • 没有。 count-matches 正在计算单个项目。 uniq -c 为列表中的多个项目提供计数

标签: emacs uniq


【解决方案1】:

我想一种常见的方法是对字符串进行哈希处理,然后打印内容。这种方法在 emacs 中很容易实现。

;; See the emacs manual for creating a hash table test
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Hash.html
(defun case-fold-string= (a b)
  (eq t (compare-strings a nil nil b nil nil t)))
(defun case-fold-string-hash (a)
  (sxhash (upcase a)))

(define-hash-table-test 'case-fold
  'case-fold-string= 'case-fold-string-hash)

(defun uniq (beg end)
  "Print counts of strings in region."
  (interactive "r")
  (let ((h (make-hash-table :test 'case-fold))
        (lst (split-string (buffer-substring-no-properties beg end) "\n"
                           'omit-nulls " "))
        (output-func (if current-prefix-arg 'insert 'princ)))
    (dolist (str lst) 
      (puthash str (1+ (gethash str h 0)) h))
    (maphash (lambda (key val)
               (apply output-func (list (format "%d: %s\n" val key))))
             h)))

选择文本时的输出

4: flower
1: park
3: stone

【讨论】:

  • 好又快,这个。不过,不确定您是否想要省略空值和行修剪行为?
  • 我想maphash 序列是未定义的?
  • @phils 对,如果需要按键/值排序,我会在 maphash 函数中添加类似 (push (cons val key) result) 的内容,然后在 (cl-sort results #'> :key #'car) 中添加内容
【解决方案2】:

我想你可以采取很多方法来解决这个问题。这是一个相当简单的方法:

(defun uniq-c (beginning end)
  "Like M-| uniq -c"
  (interactive "r")
  (let ((source (current-buffer))
        (dest (generate-new-buffer "*uniq-c*"))
        (case-fold-search nil))
    (set-buffer dest)
    (insert-buffer-substring source beginning end)
    (goto-char (point-min))
    (while (let* ((line (buffer-substring (line-beginning-position)
                                          (line-end-position)))
                  (pattern (concat "^" (regexp-quote line) "$"))
                  (count (count-matches pattern (point) (point-max))))
             (insert (format "%d " count))
             (forward-line 1)
             (flush-lines pattern)
             (not (eobp))))
    (pop-to-buffer dest)))

【讨论】:

  • 尤其是考虑到这完全基于正则表达式,没有任何用处,这不是一个非常有效的解决方案;但它应该很容易阅读/理解。
  • 此外请注意,此过程的复杂度为 O(n^2),而 jenesaisquoi 的基于散列的方法的复杂度为 O(n)。
【解决方案3】:

类似于 bash 中的uniq -c

那为什么不使用uniq -c呢?

区域突出显示后,M-| "sort | uniq -c" 将在当前区域上运行该命令。结果将显示在迷你缓冲区中,并将列在 *Messages* 缓冲区中。添加前缀 arg 会将结果插入到当前缓冲区中。

【讨论】:

  • uniq -c 在本机某些环境中不可用。这就是问题的全部原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-22
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多