在集合中返回下一个成员的惯用方法是什么?

时间:2017-08-30 02:20:09

标签: clojure

给定集合中的成员,返回集合中下一个项目的惯用方法是什么?

例如,给定(def coll [:a :b :c :d :e :f])f应该使(f coll :d)返回:e

3 个答案:

答案 0 :(得分:11)

通常情况下,这不是Clojure中非常重要的事情。唯一可能的实现需要对输入集合进行线性扫描,这意味着您使用了错误的数据结构来执行此任务。

相反,我们通常会尝试构建数据,以便于我们需要对其执行的任务。如何最好地做到这一点将取决于为什么你想要查找“foo之后的元素”。例如,如果您一次输入一个项目并想要知道下一个项目以及当前项目,则可以编写Promise以获得一系列相邻值的序列。

也就是说,你要求一个惯用的实现,但没有:成语是以不同的方式解决问题。当然,如果您认为自己处于使用正确数据结构并且只需要做一次或两次奇怪事情的特殊情况,那么自己编写循环就很简单了。

答案 1 :(得分:4)

正如@amalloy在他的回答中所说,这不是你想要使用原始数据结构的东西,因为它每次都需要线性查找。换句话说,由于其性能,您的(f coll :d)模式不会特别有用。

但是,您可以做的是定义一个函数,在给定集合的情况下,构建一个使这种查找有效的数据结构,并将其用作函数。它可能看起来像这样:

(defn after [xs]
  (into {} (map vec (partition 2 1 xs))))

示例:

(-> [:a :b :c :d :e :f] after :d)
;;=> :e

(let [xs [:a :b :c :d :e :f]
      f (after xs)]
  (map f xs))
;;=> (:b :c :d :e :f nil)

答案 2 :(得分:0)

如果我们将问题概括为找到第一件通过测试后的事情,我们会得到像

这样的东西
(defn following [pred coll]
  (->> coll
       (drop-while (complement pred))
       (second)))

例如,

(following #{6} (range))
=> 7

或者,你的例子,

(following #{:d} coll)
=> :e

这不仅仅是take-whiledrop-while的惯用语。