查看下面的功能。我想传递一个因子向量,并测试向量中的任何元素是x
的因子。我该怎么做?
(defn multiple?
"Takes a seq of factors, and returns true if x is multiple of any factor."
([x & factors] (for [e m] ))
([x factor] (= 0 (rem x factor))))
答案 0 :(得分:1)
(defn multiple? [x & factors]
(some zero? (map #(rem x %) factors)))
如果所有测试都失败,some
也返回nil
,如果您需要实际返回false
,则可以在其中放置true?
:
(defn multiple? [x & factors]
(true? (some zero? (map #(rem x %) factors))))
请注意,some
短路和map
是懒惰的,因此multiple?
会在找到匹配后立即停止。例如以下代码测试序列1,2,3,4,...
。
=> (apply multiple? 10 (map inc (range)))
true
显然,只有当multiple?
不对序列中的每个数字进行测试时,此计算才会终止。
答案 1 :(得分:1)
您只能使用some
解决此问题。
=> (defn multiple? [x factors]
(some #(zero? (rem x %)) factors))
#'user/multiple?
=> (= true (multiple? 10 [3 4]))
false
=> (= true (multiple? 10 [3 4 5 6]))
true
some
将停在第一个因素。
答案 2 :(得分:0)
尝试使用显式尾递归:
(defn multiple? [x factors]
"if any of the elements in the vector is a factor of x"
(loop [factors factors]
(cond (empty? factors) false
(zero? (rem x (first factors))) true
:else (recur (rest factors)))))
上述解决方案的优点包括:一旦发现向量中的任何元素是x
的因子,它将立即停止,而不迭代整个向量;由于使用了尾递归,它的效率很高,并且在恒定的空间内运行;它直接返回一个布尔结果,不需要考虑返回nil
的情况。像这样使用它:
(multiple? 10 [3 4])
=> false
(multiple? 10 [3 4 5 6])
=> true
如果你想避免显式传递一个向量的需要(用于调用这样的过程:(multiple? 10 3 4 5 6)
)),那么只需在参数列表中添加一个&
,就像它在问题
答案 3 :(得分:0)
更多 Clojurian 方法是编写一个更通用的函数:它不会回答真/假问题,而是返回x
的所有因子。而且因为序列是懒惰的,所以如果你想知道它是否为空,它几乎同样有效。
(defn factors [x & fs]
(for [f fs :when (zero? (rem x f))] f))
(factors 5 2 3 4)
=> ()
(factors 6 2 3 4)
=> (2 3)
然后您只需使用empty?
:
(empty? (factors 5 2 3 4))
=> true
(empty? (factors 6 2 3 4))
=> false