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])