计算物品的优雅方式

Che*_*eso 9 lisp emacs elisp

我有一个这样的列表:

  '(("Alpha" .  1538)
    ("Beta"  .  8036)
    ("Gamma" .  8990)
    ("Beta"  .  10052)
    ("Alpha" .  12837)
    ("Beta"  .  13634)
    ("Beta"  .  14977)
    ("Beta"  .  15719)
    ("Alpha" .  17075)
    ("Rho"   .  18949)
    ("Gamma" .  21118)
    ("Gamma" .  26923)
    ("Alpha" .  31609))
Run Code Online (Sandbox Code Playgroud)

如何计算列表中每个元素的汽车中术语的总出现次数?基本上我想要:

(("Alpha" . 4)
 ("Beta" . 5)
 ("Gamma" . 3)
 ("Rho" . 1))
Run Code Online (Sandbox Code Playgroud)

不,这不是功课.我还没有"在Lisp中思考"的事情.

在C#中,我会使用LINQ来执行此操作.我也可以在lisp中使用while循环等,但我想这样做的方式似乎过于复杂.


编辑

这就是我所拥有的:

(defun count-uniq (list)
  "Returns an alist, each item is a cons cell where the car is
a unique element of LIST, and the cdr is the number of occurrences of that
unique element in the list. "
  (flet ((helper (list new)
                 (if (null list)
                     new
                   (let ((elt (assoc (car list) new)))
                     (helper (cdr list)
                             (if elt
                                 (progn (incf (cdr elt)) new)
                               (cons (cons (car list) 1) new)))))))
    (nreverse (helper list nil))))
Run Code Online (Sandbox Code Playgroud)

Eli*_*lay 5

(defun freqs (list &optional test key)
  (let ((h (make-hash-table :test test)))
    (dolist (x list)
      (let ((key (if key (funcall key x) x)))
        (puthash key (1+ (gethash key h 0)) h)))
    (let ((r nil))
      (maphash #'(lambda (k v) (push (cons k v) r)) h)
      (sort r #'(lambda (x y) (< (cdr x) (cdr y)))))))

(freqs '(("Alpha" .  1538)
         ("Beta"  .  8036)
         ("Gamma" .  8990)
         ("Beta"  .  10052)
         ("Alpha" .  12837)
         ("Beta"  .  13634)
         ("Beta"  .  14977)
         ("Beta"  .  15719)
         ("Alpha" .  17075)
         ("Rho"   .  18949)
         ("Gamma" .  21118)
         ("Gamma" .  26923)
         ("Alpha" .  31609))
       #'equal #'car)
Run Code Online (Sandbox Code Playgroud)

  • @Terje Norderhaug:关于*Emacs*Lisp的问题,而不是Common Lisp.它的某些功能只有在你需要'('cl)`时才可用,但如果可能的话,通常会有一些偏好可以避免它.无论如何,链接到CLHS(正如您在此评论中所做的那样)是危险的,因为Emacs中的CL仿真并不总是像完整语言一样. (3认同)
  • `(puthash key(1+(gethash key h 0))h)`可以简化为Common Lisp中的`(incf(gethash key h 0))`.当与setf(以及incf)一起使用时,将评估提供给gethash的默认值,但值[被忽略](http://www.lispworks.com/documentation/HyperSpec/Body/f_gethas.htm). (2认同)

Tre*_*son 2

我不知道这是最优雅的,但看起来很合理:

(defun add-for-cheeso (data)
  (let (result)
    (dolist (elt data result)
      (let ((sofar (assoc (car elt) result)))
        (if sofar
            (setcdr sofar (1+ (cdr sofar)))
          (push (cons (car elt) 1) result))))))
Run Code Online (Sandbox Code Playgroud)