3

看看下面的函数。我想传递一个因子向量并测试向量中的任何元素是否是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))))
4

4 回答 4

1

您可以尝试使用someand map

(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?显然,如果不对序列中的每个数字进行测试,这种计算只能终止。

于 2012-06-19T02:11:23.567 回答
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将停止在第一个因素。

于 2012-06-19T02:34:32.810 回答
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))然后只需将 a 添加&到参数列表中,就像它在问题中一样。

于 2012-06-19T02:14:47.017 回答
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
于 2012-06-20T00:35:01.320 回答