2012-03-21 15 views
13

Ahora bien, esto funciona muy bien:Elisp: Cómo eliminar un elemento de una lista de asociación con la cadena de clave

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

Pero estoy usando cadenas como claves en mi aplicación:

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

Y esto no puede hacer nada:

(assq-delete-all "a" al) 

Creo que eso se debe a la instancia del objeto de cadena es diferente

012 (?)

Entonces, ¿cómo debería eliminar un elemento con una clave de cadena de una lista de asociación? ¿O debería renunciar y utilizar símbolos como claves en su lugar, y convertirlos en cadenas cuando sea necesario?

+1

Por cierto, debe asignar el resultado de 'assq-delete-all' a la variable aunque sea una operación destructiva:' (setq al (assq-delete-all 'a al)) '. ¿Qué sucede si la lista se vacía? El 'al' debe tomar el valor nulo: ¿cómo sucederá eso? ¿O qué pasa si elimina el primer elemento, los contras principales a los que 'al' apunta inicialmente?'al' se debe actualizar para saltar a la segunda celda. – Kaz

Respuesta

11

Si sabe que sólo puede haber una sola entrada coincidente en la lista, también se puede utilizar el siguiente formulario:

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

en cuenta que la setq (que le faltaba a su código de ejemplo) es muy importante para operaciones `delete 'en las listas; de lo contrario, la operación falla cuando el elemento eliminado es el primero en la lista.

13

El q en assq significa tradicionalmente eq igualdad se utiliza para los objetos.

En otras palabras, assq es eq con sabor .

Las cadenas no siguen eq igualdad. Dos cadenas que son secuencias de caracteres equivalentes pueden no ser eq. El assoc en Emacs Lisp usa la igualdad equal que funciona con cadenas.

Lo que necesita aquí es un assoc-delete-all para su lista de asociación basada en equal, pero esa función no existe.

Todo lo que puedo encontrar cuando la búsqueda de assoc-delete-all es esta lista de correo de rosca: http://lists.gnu.org/archive/html/emacs-devel/2005-07/msg00169.html

liar. Es bastante trivial: recorre la lista y reúne todas esas entradas en una nueva lista cuyo car no coincide con la clave dada bajo equal.

Una cosa útil a tener en cuenta podría ser la biblioteca de compatibilidad de Common Lisp. http://www.gnu.org/software/emacs/manual/html_node/cl/index.html

Aquí hay algunas funciones útiles, como remove*, con las cuales puede eliminar de una lista una función de predicado personalizada para probar los elementos. Con esto se puede hacer algo como esto:

;; 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)) 

La variante es destructiva delete*.

Cuestiones relacionadas