我想创建一个getnext fn,它在coll中查找元素,当匹配时,返回下一个元素。此外,如果最后一个元素作为参数传递,它应该返回第一个元素。
(def coll ["a" "b" "c" "d"])
(defn get-next [coll item] ...)
(get-next coll "a") ;;=> "b"
(get-next coll "b") ;;=> "c"
(get-next coll "c") ;;=> "d"
(get-next coll "d") ;;=> "a" ; back to the beginning
谢谢!
答案 0 :(得分:7)
这个怎么样:
在序列末尾附加第一项(懒惰),
删除非项目
如果找不到项目,请返回剩下的内容(nil
。
或代码:
(defn get-next [coll item]
(->> (concat coll [(first coll)])
(drop-while (partial not= item))
second))
答案 1 :(得分:4)
肯定有比这更纯粹的lisp方法,但是,嘿,只要我们得到.indexOf,我们不妨使用它。简单的关键是,加上循环,所以我们不必检查最后一项。
(defn get-next [coll item]
(nth (cycle coll) (inc (.indexOf coll item))))
一些测试运行:
(get-next ["A" "B" "C" "D"] "B")
=> "C"
(get-next ["A" "B" "C" "D"] "D")
=> "A"
(get-next ["A" "B" "C" "D"] "E")
=> "A"
糟糕!好吧,如果集合中的项目不是,我们没有指定我们想要做什么。习惯上,我们会返回nil,所以我们需要一个新的get-next:
(defn get-next-2 [coll item]
(let [i (.indexOf coll item)]
(if (= -1 i) nil (nth (cycle coll) (inc i)))))
现在我们抓住了不存在的情况:
(get-next-2 ["A" "B" "C" "D"] "Q")
=> nil
答案 2 :(得分:2)
我会将coll
转换为地图并将其用于查找:
(def doll (zipmap coll (rest (cycle coll))))
(doll "a") => "b"
(doll "b") => "c"
(doll "d") => "a"
答案 3 :(得分:1)
drop-while
这是一个很好的工作:
(defn get-next
[coll item]
(let [remainder (drop-while #(not= % item) coll)]
(when (empty? remainder)
(throw (IllegalArgumentException. (str "Item not found: " item))))
(if (< 1 (count remainder))
(nth remainder 1)
(first coll))))
(dotest
(let [coll [1 2 3 4]]
(is= 2 (get-next coll 1))
(is= 3 (get-next coll 2))
(is= 4 (get-next coll 3))
(is= 1 (get-next coll 4))
(throws? (get-next coll 5))))