如何将畸形的PLIST转换为Emacs Lisp中的一对列表



假设我们有以下畸形的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的包装器,每个软件包都是根据每个模块/图层安装的(例如spacemacsdoom-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))))

最新更新