假设我们有以下畸形的plist
(defvar mplist '(
:lang 'js 'html5 'css 'sass
:writing 'org 'markdown))
(defvar plist ())
问题是如何将mplist
转换为plist
,例如
'(
(:lang . 'js)
(:lang . 'html5)
(:lang . 'css)
(:lang . 'sass)
(:writing . 'org)
(:writing . 'markdown))
我的用例是编写一个宏,该宏是use-package
的包装器,每个软件包都是根据每个模块/图层安装的(例如spacemacs
或doom-emacs
)。
您的帮助非常感谢!
您用于 plist 的示例实际上是 alist 。
'((:lang . 'js)
(:lang . 'html5)
(:lang . 'css)
(:lang . 'sass)
(:writing . 'org)
(:writing . 'markdown))
简单地说:
- plist是 flat 键 ->值对的列表,例如
'(:a 1 :b 2 :c 3)
- alist是列表的列表,其car =键和cdr =值。
'((a . 1) (b . 2) (c . 3))
。
如果您只打算在这对列表上迭代,则Phils答案很好,但是如果您的数据集不是很小的(例如,> 40个条目),并且需要测试会员资格,即"启用了:lang css
吗?",考虑使用哈希表。
原因是,您的钥匙不是唯一的。(assq :lang alist)
将产生'(:lang . js)
。其余的第一场比赛都被遮蔽了。有了这个alist,您唯一的选择是member
:
(member '(:lang . css) alist)
,但是member
是O(n)。如果您对此感到满意,菲尔斯的回答就是您所需要的。如果您不是(例如,您经常查找),那么要么重组输入以具有唯一的符号键(例如,condenate:lang and css和CSS,例如:lang-css
),然后使用assq
(仍然更快,但更快,但是),或使用哈希表。
对于哈希表,我们需要稍微修改Phils的答案:
;; initialize the hash table if necessary
(unless table
(setq table (make-hash-table :test #'equal)))
(let (pkey)
(dolist (i mplist)
(if (keywordp i)
(setq pkey i)
;; (puthash KEY VALUE HASH-TABLE)
(puthash (cons pkey i) t table))))
然后,您可以使用(gethash '(:lang . css) table)
进行O(1)会员资格检查或与(maphash (lambda (pair _) [...]) table)
对迭代。
希望有帮助!
我希望keywordp
谓词是您要寻找的?
(let (plist pkey)
(dolist (i mplist (nreverse plist))
(if (keywordp i)
(setq pkey i)
(push (cons pkey i) plist))))