Wednesday, February 9, 2011
Partioning a Number Sequence in Clojure
I have the following input:
(def nums [123456789012 123456789012])
I'd like the following output:
[[1234 5678 9012] [1234 5678 9012]]
Note both of these sequence contain numbers not strings...
I figured this would be really simple by doing the following:
Convert each entry into a String
Partition each string by 4
Convert each partition back into an integer
Attempt 1:
(defn split-nums [nums factor]
(map
#(map
(fn [x] (Integer/valueOf (str x)))
(partition factor (str %)))
nums))
(println (split-nums nums, 4))
When I run this I get the following error:
Caused by: java.lang.NumberFormatException: For input string: "clojure.lang.LazySeq@4834333c"
Which tells me I am dealing with a lazy sequence that I need to force evaluation on but when I try to (str (doall x)) I get the same result.
Attempt 2:
A version with / and mod. This also fixes leading zeros problem.
(defn int-partition [num size]
(let [f (int (Math/pow 10 size))]
(loop [n num l ()]
(if (zero? n)
(vec l)
(recur (int (/ n f)) (conj l (mod n f)))))))
(defn split-nums [nums factor] (vec (map #(int-partition % factor) nums)))
Attempt 3:
(defn split-nums [nums factor]
(map #(map (fn [x] (Integer/valueOf (apply str x))) ; apply str
(partition factor (str %)))
nums))
(str (lazy-seq [1])) ; "clojure.lang.LazySeq@20"
(apply str (lazy-seq [1])) ; "1"
I'd probably write it to accept one number, then use map, instead of taking a coll.
(defn split-number [n factor]
(->> (str n)
(partition-all factor) ;; or partition
(map (partial apply str))
(map #(Integer/valueOf %))))
(map #(split-number % 4) [12345678 12345678]) ;; => ((1234 5678) (1234 5678))
Bingo!
No comments:
Post a Comment