我最近发现了Specter库,它提供了数据结构导航和转换功能,并使用Clojure编写。从嵌套结构中选择与Clojure中的条件匹配的元素
实施一些API作为学习练习似乎是一个好主意。幽灵实现的API拍摄功能和嵌套结构作为参数,并返回满足该功能如下面从嵌套结构元素的向量:
(select (walker number?) [1 :a {:b 2}])
=>[1 2]
下面是我在实现的功能的尝试与类似的API:
(defn select-walker [afn ds]
(vec (if (and (coll? ds) (not-empty ds))
(concat (select-walker afn (first ds))
(select-walker afn (rest ds)))
(if (afn ds) [ds]))))
(select-walker number? [1 :a {:b 2}])
=>[1 2]
我试图实现select-walker
,使用list comprehension,looping,并使用cons和conj。在所有这些情况下,返回值是一个嵌套列表,而不是元素的平面向量。
然而,我的实现似乎不像惯用的Clojure,并且时间和空间复杂性很差。
(time (dotimes [_ 1000] (select (walker number?) (range 100))))
"Elapsed time: 19.445396 msecs"
(time (dotimes [_ 1000] (select-walker number? (range 100))))
"Elapsed time: 237.000334 msecs"
请注意,我的实施比Spectre的实施慢大约12倍。
我对实施select-walker
有三个问题。
- 是否可以使用尾递归实现
select-walker
? - 可以
select-walker
写成更习惯Clojure? - 任何提示使
select-walker
执行得更快?
谢谢。我喜欢'select-walker-rec'通过嵌套ds递归的方式。类似于深度优先遍历。 – ardsrk