Definition
A map in Clojure is a key-value data structure that stores associations between keys and values.
- Keys are unique (no duplicate keys)
- Maps are unordered by default (unless you use a sorted map)
- Maps are immutable (modifications return a new map instead of modifying the original)
Clojure supports two main types of maps:
- HashMap
({})
– Unordered, optimized for fast lookup. - SortedMap
(sorted-map)
– Ordered by key, useful when ordering matters.
Syntax
A Clojure map is represented using curly braces {}
with key-value pairs:
{:key1 value1, :key2 value2, :key3 value3}
Keys are often keywords (:name), but they can also be strings, symbols, or numbers.
Values can be anything, even map.
Common Use Cases
Clojure maps are used for:
- Data Representation – Storing structured information like user profiles, configurations, etc
- Associative Lookup – Fast key-based retrieval of values
- Transformations – Using functions like assoc, dissoc, merge, map, reduce on maps
- Sorting & Grouping – Organizing data using sorted-map or group-by
Practicing:
Create and Manipulate Maps
Create a map representing a student with keys :name, :age, and :grade. Add a new key :hobby with a value, and update the :grade to a new value.
(def student {:name "Johnny" :age "30" :grade "A"})
(def studentWithHobby (assoc student :hobby "Clojure"))
(def studentGotB (assoc studentWithHobby :grade "B"))
Access Map Values
Given a map of product prices (e.g., {:apple 1.2 :banana 0.5 :cherry 2.5}), retrieve the price of :banana and handle the case where a key does not exist (e.g., :orange).
(def productPrice {:apple 1.2 :banana 0.5 :cherry 2.5})
(productPrice :banana)
(productPrice :orange 0)
Filter Map Entries
Write a function that takes a map of people’s names and ages (e.g., {:Alice 30 :Bob 25 :Charlie 35}) and returns a new map with only people aged 30 or older.
(def people {:Alice 30 :Bob 25 :Charlie 35})
(defn filter30Above [people]
(filter (fn [map-item] (> (val map-item) 30)), people)
)
Merge Maps
Merge two maps: one containing a user's personal details and another containing their contact information. Handle any key conflicts by prioritizing the second map.
(def user {:id 123456 :fNmae "Ivan" :lName "Gavlik" :age 30 })
(def contact {:id 123456 :email "ivangavlik963@gmail.com" :tel "+385912266016"})
(def user-contact (merge user contact))
Map Keys and Values Transformation
Given a map of temperatures in Celsius for different cities (e.g., {:Berlin 20 :Paris 25 :Rome 30}), transform the values to Fahrenheit.
def city-temp-celsius {:Berlin 20 :Paris 25 :Rome 30})
(defn cel-to-feh
[[key val-cel]] [key (+ (* val-cel 9/5) 32)]
)
(def city-temp-fahrenheit
(into {} (map cel-to-feh city-temp-celsius))
)
Group by Key Values
Create a function that groups a sequence of maps (e.g., {:name "Alice" :department "IT"}) by the :department key.
(def employers [ {:name "Alice" :department "IT" }
{ :name "Marko" :department "HR" }
{:name "Pero" :department "HR"}
])
(def bySector (group-by :department employers))
Remove Entries by Condition
Remove all entries from a map of products and their stock quantities (e.g., {:apples 5 :oranges 0 :pears 10}) where the stock is 0.
(def fruit-stock-quantities {:apples 5 :orange 0 :pears 10})
(defn exist-fruit-stock? [[fruit stock]]
(> stock 0)
)
(defn fruit-stock-good [fruit-stock]
(filter exist-fruit-stock? fruit-stock-quantities)
)
(def fruit-stock-report (into {} (fruit-stock-good fruit-stock-quantities)))
Nested Maps
Work with a nested map representing a school (e.g., {:class1 {:students ["Alice" "Bob"] :teacher "Ms. Smith"} :class2 {:students ["Charlie" "Dana"] :teacher "Mr. Johnson"}}). Add a new student to :class2.
(def school-class {
:class1 {:students ["Alice" "Bob"] :teacher "Ms. Smith" }
:class2 {:students ["Charlie" "Dana"] :teacher "Mr. Johnson"}
}
)
(defn new-student-class2 [student school-class]
(let [class2-students (get-in school-class [:class2 :students])
add-new-student (conj class2-students student)
class-new-student (assoc-in school-class [:class2 :students] add-new-student)
]
class-new-student
)
)
Count Map Entries
Write a function to count how many keys in a map have values greater than a given number. For example, in {:a 5 :b 10 :c 15}, count how many values are greater than 8.
(def letter-occurrence {:a 5 :b 10 :c 15})
(defn letter-occurrence-gt [n letter-occurrence]
(let [filter-map (filter #(> (second %) n) letter-occurrence)
]
(count filter-map)
)
;; (count (into [] (keys (filter #(> (second %) n) letter-occurrence))))
)
Sort Maps by Values
Sort a map of items and their prices (e.g., {:item1 20 :item2 10 :item3 30}) in ascending order of prices.
(def item-price-data {:item1 20 :item2 10 :item3 30 :item4 10})
(defn sorted-item-price [item-price] (into (sorted-map-by (fn [k1 k2]
(compare [(get item-price k1) k1] [(get item-price k2) k2]))) item-price))
Task: Managing a Library System Using Maps
Scenario:
You are developing a simple library system to manage books and their availability. The system stores book records as maps, where each book has attributes like :id, :title, :author, :year, and :available?.
Your goal is to implement functions that:
- Initialize the Library – Create a collection of book records using maps
- Check Out a Book – Update a book’s availability status when a user borrows it
- Return a Book – Update the book’s availability when a user returns it
- Find Books by Author – Retrieve all books written by a specific author
- List Available Books – Return a list of books that are currently available
- Add a New Book – Insert a new book record into the collection.
- Remove a Book – Delete a book from the collection based on its :id
Solution
(def library
[{:id 1 :title "Clojure for the Brave" :author "Daniel Higginbotham" :year 2015 :available? true}
{:id 2 :title "The Joy of Clojure" :author "Michael Fogus" :year 2014 :available? true}
{:id 3 :title "Programming Clojure" :author "Stuart Halloway" :year 2018 :available? false}])
(defn check-out-book [library book-id]
(map #(if (= (:id %) book-id)
(assoc % :available? false)
%)
library))
(defn return-book [library book-id]
(map #(if (= (:id %) book-id)
(assoc % :available? true)
%)
library))
(defn find-books-by-author [library author]
(filter #(= (:author %) author) library))
(defn list-available-books [library]
(filter :available? library))
(defn add-book [library new-book]
(conj library new-book))
(defn remove-book [library book-id]
(filter #(not= (:id %) book-id) library))
;; Example Usage
(def updated-library (check-out-book library 2))
(def returned-library (return-book updated-library 3))
(def books-by-author (find-books-by-author library "Michael Fogus"))
(def available-books (list-available-books library))
(def expanded-library (add-book library {:id 4 :title "New Book" :author "Some Author" :year 2023 :available? true}))
(def reduced-library (remove-book library 1))
Author Of article : ivan.gavlik Read full article