kazuwal
kazuwal

Reputation: 1101

How to split a number in Clojure?

I am looking for a nice method to split a number with n digits in Clojure I have these two methods:

 (->> (str 942)
      seq
      (map str)
      (map read-string)) => (9 4 2)

and...

(defn digits [n]
   (cons 
      (str (mod n 10)) (lazy-seq (positive-numbers (quot n 10)))))

(map read-string (reverse (take 5 (digits 10012)))) => (1 0 0 1 2)

Is there a more concise method for doing this type of operation?

Upvotes: 13

Views: 8447

Answers (6)

Sandeep Sarkar
Sandeep Sarkar

Reputation: 419

Easiest i could find:

(->> (str n)
   seq
   (map (comp read-string str)))

Upvotes: 0

Yar
Yar

Reputation: 7476

a looping method:

 (defn split-numbers [number]
   (loop [itr 0 res [] n number]
     (if (= n 0)
       res
       (recur (inc itr) (concat (vector (mod n 10)) res) (int (/ n 10)))
       )
     )
   )

Upvotes: 0

Thumbnail
Thumbnail

Reputation: 13483

A concise version of your first method is

(defn digits [n]
  (->> n str (map (comp read-string str))))

... and of your second is

(defn digits [n]
  (if (pos? n)
    (conj (digits (quot n 10)) (mod n 10) )
    []))

An idiomatic alternative

(defn digits [n]
  (->> n
       (iterate #(quot % 10))
       (take-while pos?)
       (mapv #(mod % 10))
       rseq))

For example,

(map digits [0 942 -3])
;(nil (9 4 2) nil)
  • The computation is essentially eager, since the last digit in is the first out. So we might as well use mapv and rseq (instead of map and reverse) to do it faster.
  • The function is transducer-ready.
  • It works properly only on positive numbers.

Upvotes: 17

vsnyc
vsnyc

Reputation: 2257

You could simply do

(map #(Character/digit % 10) (str 942))

EDIT: Adding a function definition

(defn digits [number] (map #(Character/digit % 10) (str number)))

Usage:

(digits 1234)

Note: This is concise, but does use java String and Character classes. An efficient implementation can be written using integer modulo arithmetic, but won't be concise. One such solution similar to Charles' answer would be:

(defn numTodigits
  [num]
  (loop [n num res []]
    (if (zero? n)
      res
      (recur (quot n 10) (cons (mod n 10) res)))))

Source

Upvotes: 10

Diego Basch
Diego Basch

Reputation: 13079

A recursive implementation (could be more efficient and less concise, but it shouldn't matter for reasonable numbers).

(defn digits [n]
  (when (pos? n)
    (concat (digits (quot n 10))
            [(mod n 10)])))

Upvotes: 2

Charles Duffy
Charles Duffy

Reputation: 295815

I'm not sure about concise, but this one avoids unnecessary inefficiency such as converting to strings and back to integers.

(defn digits [n]
  (loop [result (list), n n]
    (if (pos? n)
      (recur (conj result (rem n 10))
             (quot n 10))
      result)))

Upvotes: 6

Related Questions