DEV Community

ivan.gavlik
ivan.gavlik

Posted on

4

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

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series