Lisp - Representing Set with HashTable



In this chapter, we're discussing how to represent a Set with Hashtable.

Create a Set as HashTable

We're creating a set using a hashtable. A hashtable is a suitable datastructure to represent as Set as it has an average time complexity of O(1) to add, remove and contains operations.

; create a set using hashtable
(defun make-set ()
   (make-hash-table))

Add operation

This function will add an element to the set.

; define an add operation on set
(defun set-add (set item)
   ; add item to the set 
   (setf (gethash item set) t))
  • gethash item set − retrieves the hash value associated with the element in the set as hashtable.

  • setf − sets the value associated with element in the set as true. As key is present in the hashtable, it signifies that element is present in the set. If element is not present, gethash return non-nil value and setf will override the same.

Remove operation

This function will remove an element from the set.

; define remove operation on set
(defun set-remove (set item)
   (remhash item set))
  • remhash item set − removes the item entry from the set as hashtable. If item is not present, remhash does nothing and returns nil.

Contains operation

This function checks an element existence in the set.

; define contains operation on set
(defun set-contains-p (set item)
   (nth-value 1 (gethash item set)))
  • gethash item set − retrieves the hash value associated with the element in the set as hashtable and a boolean value as value is present or not.

  • nth-value 1 − retrieves the second return value, the boolean result to verify if element is present or not.

Get size operation

This function gets the size of hashtable as size of the set.

(defun set-size (set)
   (hash-table-count set))

Set to List operation

This function gets a list from a set for printing purpose. We're looping over hash keys and collecting them in a list.

; get set elements as a list
(defun set-to-list (set)
   (loop for key being the hash-keys of set
      collect key))

List to Set operation

This function gets a Set from a List. We're looping over list values and adding them to the set.

; convert a list to set
(defun list-to-set (list)
   (let ((set (make-set)))
      (dolist (element list set)
         (set-add set element))))

Example - Using hashtable as Set

Following example showcases the usage of hashtable as Set.

; create a set using hashtable
(defun make-set ()
   (make-hash-table))

; define an add operation on set
(defun set-add (set item)
   ; add item to the set 
   (setf (gethash item set) t))

; define remove operation on set
(defun set-remove (set item)
   (remhash item set))

; define contains operation on set
(defun set-contains-p (set item)
   (nth-value 1 (gethash item set)))

; get size of the set as hashtable size
(defun set-size (set)
   (hash-table-count set))

; get set elements as a list
(defun set-to-list (set)
   (loop for key being the hash-keys of set
      collect key))

; convert a list to set
(defun list-to-set (list)
   (let ((set (make-set)))
      (dolist (element list set)
         (set-add set element))))

; Example Usage:
(setf my-set (make-set))

; add elements to the set
(set-add my-set 10)
(set-add my-set 20)
; adding duplicate have no effect
(set-add my-set 10) 

; print the set
(format t "My Set: ~a~%" (set-to-list my-set))
; print the size of the set
(format t "Size of My Set: ~a~%" (set-size my-set))

; check if elements are present in the set
(format t "Contains 20? ~a~%" (set-contains-p my-set 20)) 
(format t "Contains 30? ~a~%" (set-contains-p my-set 30))

; remove an element
(set-remove my-set 10)
(format t "My Set after removing 10: ~a~%" (set-to-list my-set))

Output

When you execute the code, it returns the following result −

My Set: (20 10)
Size of My Set: 2
Contains 20? T
Contains 30? NIL
My Set after removing 10: (20)
Advertisements