我正在尝试编写一个函数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)
答案 0 :(得分:4)
此问题出现在(adjacents [1 2 3])
的第一个评估循环中,a
绑定到1
和b
绑定到2
。然后你问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
,则可能无法提供所需的结果:
user=> (adjacents [1 2 nil 4 5])
[[1 2]]
请参阅他对使用列表建议实施的评论。
请注意,Clojure的partition
可以用来完成这项工作而不会有定义自己的危险:
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))
答案 1 :(得分:0)
这是我的简短回答。一切都变成了一个载体,但它适用于所有序列。
(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
的答案。