DEV Community

ivan.gavlik
ivan.gavlik

Posted on

Clojure's map data type

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} 
Enter fullscreen mode Exit fullscreen mode

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")) 
Enter fullscreen mode Exit fullscreen mode

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) 
Enter fullscreen mode Exit fullscreen mode

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) ) 
Enter fullscreen mode Exit fullscreen mode

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)) 
Enter fullscreen mode Exit fullscreen mode

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)) ) 
Enter fullscreen mode Exit fullscreen mode

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)) 
Enter fullscreen mode Exit fullscreen mode

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))) 
Enter fullscreen mode Exit fullscreen mode

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 ) ) 
Enter fullscreen mode Exit fullscreen mode

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)))) ) 
Enter fullscreen mode Exit fullscreen mode

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)) 
Enter fullscreen mode Exit fullscreen mode

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)) 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)