2011-12-14 80 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))