如何在Clojure中拆分数字?

13

我正在寻找一种在Clojure中拆分n位数字的好方法,我有以下两种方法:

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

以及...

(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)

有没有更简洁的方法来执行这种类型的操作?


你可以将你的第一个方法简化为(->> 942 str (map (comp read-string str))) - Thumbnail
确实!非常感谢 ;) - kazuwal
我已经将它和你的第二种方法的相应缩写添加到我的答案中。 - Thumbnail
6个回答

17
您的第一种方法的简明版本为:
(defn digits [n]
  (->> n str (map (comp read-string str))))

...而你的第二个则是

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

一种惯用语的替代方法

(defn digits [n]
  (->> n
       (iterate #(quot % 10))
       (take-while pos?)
       (mapv #(mod % 10))
       rseq))
例如,
(map digits [0 942 -3])
;(nil (9 4 2) nil)
  • 因为计算中的最后一位是输出的第一位,所以计算实际上是急切的。 因此,我们可以使用mapvrseq(而不是mapreverse)来加速计算。
  • 该函数已准备好成为变换器。
  • 它仅在正数上正常工作。

10

您可以简单地执行

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

编辑:添加函数定义

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

使用方法:

(digits 1234)
注意:这个实现虽然简洁,但使用了Java中的String和Character类。可以通过使用整数模算术编写高效的实现,但这种实现不会很简洁。一个类似于Charles答案的解决方案如下:
(defn numTodigits
  [num]
  (loop [n num res []]
    (if (zero? n)
      res
      (recur (quot n 10) (cons (mod n 10) res)))))

来源


6

我不确定这是否简洁,但这个方法避免了不必要的低效率,例如将数字转换为字符串再转回整数。

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

2

递归实现(可能不够高效且不够简洁,但对于合理的数字应该没有问题)。

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

2
在处理非常大的数字时,需要小心堆栈溢出的问题。 - Charles Duffy
1
建立一个单项向量只是为了进行“concat”并不是一个很好的想法。由于(mod n 10)的结果始终是一个单个数字,因此conjcons将是更好的选择。 - muhuk
@mujuk consconj将构建反向列表。@Charles 我同意,我只是试图写出简洁的东西。如果要求说明输入可能有数千个数字,我就不会使用纯递归了。 - Diego Basch
@Diego,conj 方法构建正序列表或倒序列表取决于你的集合类型。 - Charles Duffy

0
一个循环方法:
 (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)))
       )
     )
   )

0

我能找到的最简单的方法:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接