2011-12-14 54 views
17

循环一个alist并在Emacs Lisp中为每一对执行操作的最佳方式是什么?我想一个宏并不难,我只是想知道这是否构建在某个地方。有没有比下面更优雅的方式?Elisp - 在alist上循环

(setq my-list '((a . 1) 
       (b . 2) 
       (c . 3))) 

(loop for key in (mapcar 'car my-list) 
     for value in (mapcar 'cdr my-list) 
     collect (cons value key)) 

;; Returns this 
((1 . a) 
(2 . b) 
(3 . c)) 

回答

22

CL-macs.el具有用于破坏等CL支持:

(loop for (key . value) in my-list 
     collect (cons value key)) 
14

另一种方式来做到这一点没有loopmapcar和拉姆达。我不认为这是任何更优雅,但它更地道的elisp的,而不是Common Lisp的:

(mapcar (lambda (element) 
     (let ((key (car element)) 
      (value (cdr element))) 
     (cons value key))) 
     '((1 . a) (2 . b))) 
+0

我更喜欢这个答案,因为它不使用`cl`。 – kindahero 2011-12-15 02:33:33

+1

@kindahero你意识到循环是一个CL宏吗?这很好。 – 2011-12-15 04:23:34

14

目前尚不清楚,正是你想做的事 - 问题是非常普遍的。有很多方法可以循环使用alist,并对其中的一些或全部条目执行操作。你自己展示一种方式。也请看while,特别是dolist。这是使用dolist您的例子:(有可能是使用loop比你的例子更好的方式 - 没有必要建立三个列表(二mapcar S + loop),例如)

 
    (let ((res ())) 
    (dolist (x my-list) 
     (push (cons (cdr x) (car x)) res)) 
    (nreverse res)) 

6

dash.el提供了许多列表操作功能,如maps。那些接受函数作为参数的也有anaphoric对应。这允许简化functional代码。 dash.el函数以破折号开头,因此名称和指代版本以2破折号开头。所以ataylor's variant会看起来好像这样:

(--map (cons (cdr it) (car it)) '((1 . a) (2 . b))) ; ((a . 1) (b . 2))