问题
I am looking for a nice method to split a number with n digits in Clojure I have these two verbose inefficient methods:
(->> (str 942)
seq
(map str)
(map read-string)) => (9 4 2)
and...
(defn digits [n] ;YUK!!
(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 sort of operation?
回答1:
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
andrseq
(instead ofmap
andreverse
) to do it faster. - The function is transducer-ready.
- It works properly only on positive numbers.
回答2:
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
回答3:
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)))
回答4:
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)])))
回答5:
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)))
)
)
)
回答6:
Easiest i could find:
(->> (str n)
seq
(map (comp read-string str)))
来源:https://stackoverflow.com/questions/29929325/how-to-split-a-number-in-clojure