2017-09-09 1 views
1

Disons que nous avons le plist malformé suivantComment convertir un plist malformé en une liste de paires dans Emacs Lisp?

(defvar mplist '(
       :lang 'js 'html5 'css 'sass 
       :writing 'org 'markdown)) 
(defvar plist()) 

La question est de savoir comment convertir mplist en plist par exemple

'(
(:lang . 'js) 
(:lang . 'html5) 
(:lang . 'css) 
(:lang . 'sass) 
(:writing . 'org) 
(:writing . 'markdown)) 

Mon cas d'utilisation est d'écrire une macro qui est une enveloppe de use-package , chaque paquet est installé en fonction de chaque module/couche (par exemple spacemacs ou doom-emacs).

Vos aides sont appréciées!

Répondre

2

L'exemple que vous avez utilisé pour un plist est en fait un alist.

'((:lang . 'js) 
    (:lang . 'html5) 
    (:lang . 'css) 
    (:lang . 'sass) 
    (:writing . 'org) 
    (:writing . 'markdown)) 

Pour le dire simplement:

  • A plist une liste plat de paires de valeurs, par exemple des claviers>'(:a 1 :b 2 :c 3)
  • Une alist est une liste de listes, dont car = la clé et cdr = la valeur. '((a . 1) (b . 2) (c . 3)).

Si vous ne souhaitez itérer sur cette liste de paires, Phils réponse est bien, mais si votre ensemble de données est pas minuscule (par exemple,> 40 entrées) et vous devez tester l'adhésion, à savoir « Est-:lang css activé? ", envisagez d'utiliser un hash table.

Raison d'être, vos clés ne sont pas uniques. (assq :lang alist) donnera '(:lang . js). Le reste est ombragé par ce premier match. Avec ce alist votre seul choix est member:

(member '(:lang . css) alist) 

Mais member est O (n). Si cela vous convient, encore une fois, la réponse de phils est ce dont vous avez besoin. Si vous ne le faites pas (par exemple, vous effectuez fréquemment des recherches), restructurez l'entrée pour avoir des clés de symboles uniques (par exemple concaténer: lang et css en un symbole, comme :lang-css) et utilisez assq (toujours O (n), mais plus vite), ou utilisez un hash table à la place.

Pour une table de hachage, nous avons besoin de modifier légèrement la réponse de 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)))) 

Ensuite, vous pouvez faire une O (1) chèque d'adhésion avec (gethash '(:lang . css) table) ou itérer sur des paires avec (maphash (lambda (pair _) [...]) table).

Espérons que ça aide!

1

Je pense que le prédicat keywordp est ce que vous cherchez?

(let (plist pkey) 
    (dolist (i mplist (nreverse plist)) 
    (if (keywordp i) 
     (setq pkey i) 
     (push (cons pkey i) plist)))) 
+0

tks u @phils, ça a du sens pour moi! – babygau