Tuesday, 10 March 2009

Generate a random string in Clojure

In my quest to learn Lisp, I discovered Clojure, a List inspired language on the JVM. I really like it and hope to be able to use it more and more.
Here's a code snippet to generate a random string in Clojure. This is something I end up using a many projects. This is a version that is not made to be the shortest, but the most readable. And as you can see, access to Java's classes and libraries is very easy:


:use java's random generator
(def random (java.util.Random.))
;define characters list to use to generate string
(def chars
(map char (concat (range 48 58) (range 66 92) (range 97 123))))
;generates 1 random character
(defn random-char []
(nth chars (.nextInt random (count chars))))
; generates random string of length characters
(defn random-string [length]
(apply str (take length (repeatedly random-char))))


Suggestions to improve the code are welcome, I'm still a newbie in Lisp-style programming and Clojure!

12 comments:

  1. A slightly modified version, without using Java's random and with corrected ranges for the characters. (Annoying that blogger won't allow code or pre tags...)

    (def VALID-CHARS
    (map char (concat (range 48 58) ; 0-9
    (range 66 91) ; A-Z
    (range 97 123)))) ; a-z

    (defn random-char []
    (nth VALID-CHARS (rand (count VALID-CHARS))))

    (defn random-str [length]
    (apply str (take length (repeatedly random-char))))

    ReplyDelete
  2. Jeff, I think you meant:

    (range 65 91) ; A-Z

    Don't want to forget A!

    ReplyDelete
  3. Jeff, your random-char function could be simplified like this:

    (defn random-char []
    (random-nth VALID-CHARS))

    ReplyDelete
  4. Yeah, now we can use rand-nth, but this function wasn't around when I first commented.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. This is my version:

    (defn random-string [length]
    (let [ascii-codes (concat (range 48 58) (range 66 91) (range 97 123))]
    (apply str (repeatedly length #(char (rand-nth ascii-codes))))))

    ReplyDelete
  7. Exactly what I was looking for, thanks!

    ReplyDelete
  8. UUID version:

    (defn new-uuid []
    (java.util.UUID/randomUUID))

    https://coderwall.com/p/dtw0sg

    ReplyDelete
  9. (Integer/toString (.nextInt random) 36)

    ReplyDelete
  10. Microsoft-style product keys

    (defn r1ss [] (clojure.string/upper-case (Integer/toString (.nextInt random Integer/MAX_VALUE) 36)))
    (defn r25s [] (->> (repeatedly r1ss)
    (apply concat)
    (take 25)
    (partition 5)
    (map (partial apply str))
    (interpose "-")
    (apply str)))

    ReplyDelete