clojure:可以回退到第一个项目的下一个元素

时间:2018-04-12 02:24:24

标签: clojure

我想创建一个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

谢谢!

4 个答案:

答案 0 :(得分:7)

这个怎么样:

  1. 在序列末尾附加第一项(懒惰),

  2. 删除非项目

  3. 如果找不到项目,请返回剩下的内容(nil

  4. 或代码:

        (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))))