4

我正在尝试编写一个adjacents返回序列相邻对向量的函数。所以(adjacents [1 2 3])会回来[[1 2] [2 3]]

(defn adjacents [s]
  (loop [[a b :as remaining] s
          acc []]
    (if (empty? b)
      acc
      (recur (rest remaining) (conj acc (vector a b))))))

我当前的实现适用于字符串序列,但对于整数或字符,REPL 输出此错误:

IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:494)
4

2 回答 2

5

这里的问题是在 , 的第一个评估循环中(adjacents [1 2 3])绑定a1b2。然后你问b是不是empty?。但是empty?适用于序列并且b不是序列,它是Long,即2。您可以在这种情况下使用的谓词是nil?

user=> (defn adjacents [s]
  #_=>   (loop [[a b :as remaining] s acc []]
  #_=>     (if (nil? b)
  #_=>       acc
  #_=>       (recur (rest remaining) (conj acc (vector a b))))))
#'user/adjacents
user=> (adjacents [1 2 3 4 5])
[[1 2] [2 3] [3 4] [4 5]]

但是,正如@amalloy 指出的那样,如果您nil的数据中有合法的 s,这可能无法给出预期的结果:

user=> (adjacents [1 2 nil 4 5])
[[1 2]]

有关使用列表的建议实施,请参阅他的评论。

请注意,partition可以使用 Clojure 来完成这项工作,而无需定义自己的危险:

user=> (partition 2 1 [1 2 3 4 5])
((1 2) (2 3) (3 4) (4 5))
user=> (partition 2 1 [1 2 nil 4 5])
((1 2) (2 nil) (nil 4) (4 5))
于 2013-01-21T23:25:32.190 回答
3

这是我的简短回答。一切都成为向量,但它适用于所有序列。

(defn adjacent-pairs [s] 
  {:pre [(sequential? s)]}
  (map vector (butlast s) (rest s)))

测试:

user=> (defn adjacent-pairs [s] (map vector (butlast s) (rest s))) 
#'user/adjacent-pairs
user=> (adjacent-pairs '(1 2 3 4 5 6))
([1 2] [2 3] [3 4] [4 5] [5 6])
user=> (adjacent-pairs [1 2 3 4 5 6])
([1 2] [2 3] [3 4] [4 5] [5 6])
user=> 

但是,此答案可能不如partition上面使用的答案有效。

于 2013-09-01T22:49:58.867 回答