Clojure 中的一级序列展平功能是什么?我现在正在使用apply concat
,但我想知道在标准库或 clojure-contrib 中是否有内置函数。
问问题
10287 次
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 回答