When we want to get elements from a collection, but not the last element(s), we can use the function butlast
and drop-last
. The function butlast
returns all elements before the last element. If we use the function on an empty collection we get back a nil
result. When we use the function drop-last
we get back a lazy sequence. Also we can use an extra argument for the function to indicate how many of the last elements we don't want in the result. If we use drop-last
on an emtpy collection we get back an empty lazy sequence.
In the following example we use both functions with several collections:
(ns mrhaki.core.butlast (:require [clojure.test :refer [is]])) ;; Sample vector with some JVM langauges. (def languages ["Clojure" "Groovy" "Java"]) ;; Sample map describing a user. (def user {:alias "mrhaki" :first "Hubert" :last "Klein Ikkink" :country "The Netherlands"}) ;; Using butlast to get all elements but ;; not the last element as a sequence. (is (= '("Clojure" "Groovy") (butlast languages))) ;; We can also use butlast on a map, the result ;; is a sequence with vectors containing the ;; key/value pairs from the original map. (is (= '([:alias "mrhaki"] [:first "Hubert"] [:last "Klein Ikkink"]) (butlast user)) ;; We can use the into function to transform this ;; into a map again. (= {:alias "mrhaki" :first "Hubert" :last "Klein Ikkink"} (into {} (butlast user)))) ;; Returns nil when collection is empty. (is (= nil (butlast []))) ;; drop-last returns a lazy sequence with all ;; elements but the last element. (is (= '("Clojure" "Groovy") (drop-last languages))) ;; Returns an empty sequence when collection is empty. (is (= '() (drop-last []))) ;; We can use an extra argument with but-last ;; to indicate the number of items to drop ;; from the end of the collection. ;; butlast cannot do this. (is (= ["Clojure"] (drop-last 2 languages))) ;; drop-last works on maps just like butlast. (is (= '([:alias "mrhaki"]) (drop-last 3 user)) (= {:alias "mrhaki"} (into {} (drop-last 3 user))))
Written with Clojure 1.11.1.