2012-03-21 17 views
13

Teraz to działa dobrze:Elisp: Jak usunąć element z listy stowarzyszenia sznurkiem klucza

(setq al '((a . "1") (b . "2"))) 
(assq-delete-all 'a al) 

Ale używam ciągi jako klucze w mojej aplikacji:

(setq al '(("a" . "foo") ("b" . "bar"))) 

I to nie robić nic:

(assq-delete-all "a" al) 

myślę, że to dlatego, że instancja obiektu ciąg różni

012 (?)

Jak zatem usunąć element z kluczem ciągu z listy powiązań? Czy powinienem zrezygnować i używać symboli jako kluczy, a następnie w razie potrzeby zamieniać je na ciągi?

+1

Nawiasem mówiąc, musisz przypisać wynik zmiennej 'assq-delete-all' do zmiennej, nawet jeśli jest to operacja niszcząca:' (setq al (assq-delete-all 'a al)) '. Co się stanie, jeśli lista stanie się pusta? "Al" musi przyjąć wartość zero: jak to się stanie? A co jeśli usuniesz pierwszy element, główne minusy, na które początkowo wskazuje "al"?'al' musi zostać zaktualizowany, aby przejść do drugiej komórki. – Kaz

Odpowiedz

11

Jeśli wiesz, że nie może być tylko jeden wpis pasujący na liście, można również skorzystać z poniższego formularza:

(setq al (delq (assoc <string> al) al) 

Zauważ, że setq (który zaginął z przykładowego kodu) jest bardzo ważne dla operacji "delete" na listach, w przeciwnym razie operacja nie powiedzie się, gdy usunięty element stanie się pierwszym na liście.

13

Domyślnie oznacza to, że dla obiektów jest używana równość.

Innymi słowy, assq to eq o smaku .

Struny nie są zgodne z równością eq. Dwa ciągi, które są równoważnymi sekwencjami znaków, mogą nie być eq. The assoc w Emacs Lisp używa równości, która działa z ciągami.

Potrzebna jest tutaj assoc-delete-all dla Twojej listy powiązań opartych na equal, ale ta funkcja nie istnieje.

Wszystko mogę znaleźć podczas wyszukiwania assoc-delete-all jest to lista dyskusyjna wątek: http://lists.gnu.org/archive/html/emacs-devel/2005-07/msg00169.html

Rolka własną rękę. To dość trywialne: maszerujesz w dół listy i zbierasz wszystkie wpisy na nową listę, której car nie pasuje do podanego klucza pod numerem equal.

Warto przyjrzeć się bibliotece kompatybilności z Common Lisp. http://www.gnu.org/software/emacs/manual/html_node/cl/index.html

Istnieje kilka przydatnych funkcji, takich jak remove*, za pomocą których można usunąć z listy z niestandardową funkcją predykatu do testowania elementów. Z tym można zrobić coś takiego:

;; remove "a" from al, using equal as the test, applied to the car of each element 
(setq al (remove* "a" al :test 'equal :key 'car)) 

Wariant destrukcyjny jest delete*.