How can I remove an item from a sequence in Clojure?

Robert Campbell picture Robert Campbell · Jun 2, 2009 · Viewed 27.8k times · Source

First, I assume each structure-specific sequences would have different ways to remove an item: Vectors could be by index, List could be remove first or last, Set should be passing of the actual item to remove, etc.

Second, I assume there are some methods for removal that are structure agnostic; they work on seq interface.

Since sequences are immutable in Clojure, I suspect what you're actually doing is making a cheap copy of the original, only without the original item. This means list comprehension could be used for removal, but I suspect it would be unnecessarily verbose.

Please give some idiomatic examples of the different ways to remove items from Clojure sequences.

Answer

Brian Carper picture Brian Carper · Jun 2, 2009

There is no single interface for removing things from all of Clojure's data structure types, possibly because of the different performance characteristics.

(disj #{:foo :bar} :foo)       ; => #{:bar}
(dissoc {:foo 1 :bar 2} :foo)  ; => {:bar 2}
(pop [:bar :foo])              ; => [:bar]
(pop (list :foo :bar))         ; => (:bar)

These also work (returning a seq):

(remove #{:foo} #{:foo :bar})      ; => (:bar)
(remove #{:foo} [:foo :bar])       ; => (:bar)
(remove #{:foo} (list :foo :bar))  ; => (:bar)

This doesn't work for hash-maps because when you iterate over a map, you get key/value pairs. But this works:

(remove (fn [[k v]] (#{:foo} k)) {:foo 1 :bar 2})  ; => ([:bar 2])