我正在寻找一个很好的方法来分割Clojure中的n位数字我有这两个冗长的低效方法:
(->> (str 942)
seq
(map str)
(map read-string)) => (9 4 2)
Run Code Online (Sandbox Code Playgroud)
和...
(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)
Run Code Online (Sandbox Code Playgroud)
有没有更简洁的方法来进行这种类型的操作?
你可以干脆做
(map #(Character/digit % 10) (str 942))
编辑:添加功能定义
(defn digits [number] (map #(Character/digit % 10) (str number)))
Run Code Online (Sandbox Code Playgroud)
用法:
(digits 1234)
Run Code Online (Sandbox Code Playgroud)
注意:这很简洁,但确实使用java String和Character类.可以使用整数模运算来编写有效的实现,但不会简洁.类似于查尔斯答案的一个这样的解决方案是:
(defn numTodigits
[num]
(loop [n num res []]
(if (zero? n)
res
(recur (quot n 10) (cons (mod n 10) res)))))
Run Code Online (Sandbox Code Playgroud)
第一种方法的简洁版本是
(defn digits [n]
(->> n str (map (comp read-string str))))
Run Code Online (Sandbox Code Playgroud)
......而你的第二个是
(defn digits [n]
(if (pos? n)
(conj (digits (quot n 10)) (mod n 10) )
[]))
Run Code Online (Sandbox Code Playgroud)
一个惯用的替代品
(defn digits [n]
(->> n
(iterate #(quot % 10))
(take-while pos?)
(mapv #(mod % 10))
rseq))
Run Code Online (Sandbox Code Playgroud)
例如,
(map digits [0 942 -3])
;(nil (9 4 2) nil)
Run Code Online (Sandbox Code Playgroud)
mapv和rseq(而不是map和reverse)更快地完成它.我不确定简洁,但这个避免了不必要的低效率,如转换为字符串和返回整数.
(defn digits [n]
(loop [result (list), n n]
(if (pos? n)
(recur (conj result (rem n 10))
(quot n 10))
result)))
Run Code Online (Sandbox Code Playgroud)