40

Clojure 中的一级序列展平功能是什么?我现在正在使用apply concat,但我想知道在标准库或 clojure-contrib 中是否有内置函数。

4

3 回答 3

24

我的一般首选是apply concat. 此外,不要忽视(for [subcoll coll, item subcoll] item)- 根据更广泛的上下文,这可能会导致更清晰的代码。

于 2012-05-24T09:46:50.953 回答
21

没有标准功能。apply concat在很多情况下是一个很好的解决方案。或者您可以等效地使用mapcat seq.

问题apply concat在于,当集合/序列以外的任何其他内容位于第一级时,它会失败:

(apply concat [1 [2 3] [4 [5]]])
=> IllegalArgumentException Don't know how to create ISeq from: java.lang.Long...

因此,您可能想要执行以下操作:

(defn flatten-one-level [coll]  
  (mapcat  #(if (sequential? %) % [%]) coll))

(flatten-one-level [1 [2 3] [4 [5]]])
=> (1 2 3 4 [5])

作为更一般的观点,缺少内置函数通常不应该阻止您定义自己的:-)

于 2012-05-24T02:54:13.897 回答
10

apply concat也使用 - 我认为核心中没有其他任何东西。

flatten是多个级别(并且通过树遍历定义,而不是根据重复的单级扩展来定义)

另请参阅Clojure:半展平嵌套序列,其中包含flatten-1来自clojure mvc的嵌套序列(并且比我预期的要复杂得多)。

更新以澄清懒惰:

user=> (take 3 (apply concat (for [i (range 1e6)] (do (print i) [i]))))
012345678910111213141516171819202122232425262728293031(0 1 2)

您可以看到它对参数进行了 32 次评估——这是为了提高效率而分块,否则是懒惰的(它不会评估整个列表)。有关分块的讨论,请参见http://isti.bitbucket.org/2012/04/01/pipes-clojure-choco-1.html末尾的评论

于 2012-05-23T15:48:00.973 回答