Clojure:半嵌套的序列

我有一个embedded列表的向量列表,如下所示:

(([1 2]) ([3 4] [5 6]) ([7 8]))

我所知道的并不理想。 我想把它弄平([1 2] [3 4] [5 6] [7 8])

压平不起作用:它给我(1 2 3 4 5 6 7 8)

我该怎么做呢? 我想我需要创build一个新的列表基于每个列表项的内容 ,而不是项目,这是我无法find如何从文档做的一部分。

如果你只想把它变平,你可以使用concat

 (apply concat '(([1 2]) ([3 4] [5 6]) ([7 8]))) => ([1 2] [3 4] [5 6] [7 8]) 

要将列表列表转换为包含每个子列表元素的单个列表,您需要按照nickik的build议apply concat

但是,通常有一个更好的解决scheme:不要生成列表的列表! 例如,让我们想象一下你有一个名为get-names-for的函数get-names-for它需要一个符号,并返回所有可以调用该符号的很酷东西的列表:

 (get-names-for '+) => (plus add cross junction) 

如果你想获得一些符号列表的所有名字,你可以试试

 (map get-names-for '[+ /]) => ((plus add cross junction) (slash divide stroke)) 

但是这会导致你遇到的问题。 你可以用一个apply concat粘在一起,但更好的办法是使用mapcat而不是map来开始:

 (mapcat get-names-for '[+ /]) => (plus add cross junction slash divide stroke) 

flatten代码相当短:

 (defn flatten [x] (filter (complement sequential?) (rest (tree-seq sequential? seq x)))) 

它使用tree-seq遍历数据结构并返回一系列primefaces。 既然我们想要所有的底层序列,我们可以像这样修改它:

 (defn almost-flatten [x] (filter #(and (sequential? %) (not-any? sequential? %)) (rest (tree-seq #(and (sequential? %) (some sequential? %)) seq x)))) 

所以我们返回所有不包含序列的序列。

你也可能会发现有用的这个通用的1级扁平函数,我发现clojuremvc :

 (defn flatten-1 "Flattens only the first level of a given sequence, eg [[1 2][3]] becomes [1 2 3], but [[1 [2]] [3]] becomes [1 [2] 3]." [seq] (if (or (not (seqable? seq)) (nil? seq)) seq ; if seq is nil or not a sequence, don't do anything (loop [acc [] [elt & others] seq] (if (nil? elt) acc (recur (if (seqable? elt) (apply conj acc elt) ; if elt is a sequence, add each element of elt (conj acc elt)) ; if elt is not a sequence, add elt itself others))))) 

例:

 (flatten-1 (([1 2]) ([3 4] [5 6]) ([7 8]))) =>[[1 2] [3 4] [5 6] [7 8]] 

concat exampe确实为你做了工作,但是这个flatten-1允许一个集合中的非seq元素

 (flatten-1 '(1 2 ([3 4] [5 6]) ([7 8]))) =>[1 2 [3 4] [5 6] [7 8]] ;whereas (apply concat '(1 2 ([3 4] [5 6]) ([7 8]))) => java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer 

不pipe嵌套是否不均匀,这个函数都会平滑到序列级:

 (fn flt [s] (mapcat #(if (every? coll? %) (flt %) (list %)) s)) 

所以如果你的原始序列是:

 '(([1 2]) (([3 4]) ((([5 6])))) ([7 8])) 

你仍然会得到相同的结果:

 ([1 2] [3 4] [5 6] [7 8])