在Clojure中,一级序列展平函数是什么? 我目前正在使用apply concat
,但我想知道是否有内置函数可用,无论是在标准库还是clojure-contrib中。
在Clojure中,一级序列展平函数是什么? 我目前正在使用apply concat
,但我想知道是否有内置函数可用,无论是在标准库还是clojure-contrib中。
我的通常首选是apply concat
。此外,不要忽视(for [subcoll coll, item subcoll] item)
——根据上下文,这可能会导致更清晰的代码。
mapcat identity
就是我需要的。感谢您的回答! - missingfaktor没有标准函数。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])
apply concat
所提供的行为。 - missingfaktorapply concat
——我认为核心中没有其他东西了。
flatten
是多级的(并且是通过树遍历定义的,而不是通过重复单层展开定义的)。flatten-1
(比我预期的要复杂得多)。
更新以澄清惰性: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末尾的注释。
apply
,这种用法是否合理?它不比必要的方法更慢吗? - missingfaktor(apply (fn [& args] (first args)) (range 1e5))
仍然非常快,只需将函数指针传递给列表的起始位置。concat具有类似的“形状”,因此同样便宜。 - amalloy