次のようなベクトルのリストが埋め込まれたリストがあります。
(([1 2]) ([3 4] [5 6]) ([7 8]))
私が知っていることは、一緒に作業するのに理想的ではありません。これを([1 2] [3 4] [5 6] [7 8])
にフラット化したいと思います。
flattenは機能しません:それは私に(1 2 3 4 5 6 7 8)
を与えます。
どうすればよいですか?アイテムではなく、各リストアイテムのcontentsに基づいて新しいリストを作成する必要があると思います。この部分は、ドキュメントから方法を見つけることができません。
1レベルだけフラットにしたい場合は、concat
を使用できます。
(apply concat '(([1 2]) ([3 4] [5 6]) ([7 8])))
=> ([1 2] [3 4] [5 6] [7 8])
リストのリストをすべてのサブリストの要素を含む単一のリストに変換するには、nickikが示唆するようにapply concat
が必要です。
ただし、通常はより良い解決策があります。最初からリストのリストを作成しないでください。たとえば、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
データ構造をウォークスルーし、原子のシーケンスを返します。すべての最下位シーケンスが必要なので、次のように変更できます。
(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, e.g. [[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
例は確かにあなたのために仕事をします、しかしこれは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
ネストが不均一であるかどうかに関係なく、シーケンスレベルまでフラット化する関数は次のとおりです。
(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])