Подтвердить что ты не робот

Elisp: удаление элемента из списка ассоциаций со строковым ключом

Теперь это работает отлично:

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

Но я использую строки как ключи в своем приложении:

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

И это ничего не может сделать:

(assq-delete-all "a" al)

Я думаю, что поскольку экземпляр строкового объекта отличается (?)

Итак, как я должен удалить элемент со строковым ключом из списка ассоциаций? Или я должен отказаться от использования символов в качестве ключей и преобразовать их в строки при необходимости?

4b9b3361

Ответ 1

Если вы знаете, что в вашем списке может быть только одна соответствующая запись, вы также можете использовать следующую форму:

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

Обратите внимание, что setq (который отсутствовал в вашем примере кода) очень важен для операций "delete" в списках, иначе операция завершится неудачно, когда удаленный элемент окажется первым в списке.

Ответ 2

q assq традиционно означает eq для объектов используется равенство.

Другими словами, assq является eq ароматизированным assoc.

Строки не соответствуют равенству eq. Две строки, эквивалентные последовательностям символов, могут не быть eq. assoc в Emacs Lisp использует equal равенство, которое работает со строками.

Итак, вам нужен assoc-delete-all для вашего списка ассоциаций с equal, но эта функция не существует.

Все, что я могу найти, когда я ищу assoc-delete-all, это этот список рассылки: http://lists.gnu.org/archive/html/emacs-devel/2005-07/msg00169.html

Сканируй свой собственный. Это довольно тривиально: вы маршируете по списку и собираете все эти записи в новый список, чей car не соответствует указанному ключу в equal.

Одна полезная вещь, на которую можно обратить внимание, - это библиотека совместимости Common Lisp. http://www.gnu.org/software/emacs/manual/html_node/cl/index.html

Здесь есть некоторые полезные функции, такие как remove*, с помощью которых вы можете удалить из списка пользовательскую предикатную функцию для тестирования элементов. С этим вы можете сделать что-то вроде этого:

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

Деструктивный вариант delete*.