The ElispManual does a stand-up job of introducing the builtin functions for operating with association lists, see Association Lists. Modifying association lists can be done with ‘setf’ with ‘alist-get’ (often there is no need to modify an list though, just cons the new entry onto the list).

    (setq test-alist '((a . 0) (b . 1)))
    ==> ((a . 0) (b . 1))
    (setf (alist-get 'a test-alist) 9)
    (setf (alist-get 'c test-alist) 3)
    test-alist ==> ((c . 3) (a . 9) (b . 1))

To delete a key-value pair, pass a non-nil ‘REMOVE’ argument to ‘alist-get’:

    (setf (alist-get 'c test-alist nil t) nil)
    test-alist ==> ((c . 3) (b . 1))

In older Emacs versions lacking ‘alist-get’ the same things can be done with a bit more verbosity:

    (let* ((entry (assq 'a test-alist)))
      (if entry (setcdr entry 9)
	(push (cons 'a 9) test-alist)))
    (let* ((entry (assq 'c test-alist)))
      (if entry (setcdr entry 3)
	(push (cons 'c 3) test-alist)))
    (setq test-alist (assq-delete-all 'a test-alist))

Alternatively, APEL provides alist.el with similar functionality, though with a slightly different interface (note that its ‘set-alist’, ‘remove-alist’, and ‘set-modified-alist’ functions can only operate on dynamic variables, see Lexical Binding).

See also AlistVsPlist.