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

Clojure 返回集合中的下一个成员的惯用方法是什么?,clojure,Clojure,对于集合中的成员,返回集合中下一项的惯用方法是什么 例如,给定(def coll[:a:b:c:d:e:f]),那么f应该如何使(f coll:d)返回:e?通常,这不是一个人在Clojure中经常做的事情。唯一可能的实现需要对输入集合进行线性扫描,这意味着您在此任务中使用了错误的数据结构 相反,我们通常尝试对数据进行结构化处理,以便于执行需要在数据上执行的任务。如何最好地做到这一点将取决于为什么要查找“foo之后的元素”。例如,如果要一次输入一个项目,并且希望知道下一个项目和当前项目,则可以编

对于集合中的成员,返回集合中下一项的惯用方法是什么


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

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

相反,我们通常尝试对数据进行结构化处理,以便于执行需要在数据上执行的任务。如何最好地做到这一点将取决于为什么要查找“foo之后的元素”。例如,如果要一次输入一个项目,并且希望知道下一个项目和当前项目,则可以编写
(分区2 1输入)
,以获得相邻值对的序列


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

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

相反,我们通常尝试对数据进行结构化处理,以便于执行需要在数据上执行的任务。如何最好地做到这一点将取决于为什么要查找“foo之后的元素”。例如,如果要一次输入一个项目,并且希望知道下一个项目和当前项目,则可以编写
(分区2 1输入)
,以获得相邻值对的序列


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

正如@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)

正如@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)

如果我们把这个问题推广到在通过测试的第一件事之后发现另一件事,我们会得到如下结果

(defn following [pred coll]
  (->> coll
       (drop-while (complement pred))
       (second)))
比如说,

(following #{6} (range))
=> 7
或者你的例子,

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

这与
take while
drop while
差不多是惯用的用法

如果我们把这个问题推广到在通过测试的第一件事之后找到一件事,我们会得到如下结果

(defn following [pred coll]
  (->> coll
       (drop-while (complement pred))
       (second)))
比如说,

(following #{6} (range))
=> 7
或者你的例子,

(following #{:d} coll)
=> :e
这与
take while
drop while
差不多是惯用的用法