Skip to content

clojure.core/flatten

View this page on ClojureDocs

Type: function Added: Clojure 1.2 Examples: 2 Runnable: 1
([x])

Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat lazy sequence. (flatten nil) returns an empty sequence.

Examples

by dakrone on . May have evaluation errors.
by bsima on

Note by steveminer

(flatten nil) actually returns an empty sequence, not nil. The doc string is fixed in 1.4.

Note by steveminer

As shown in the example, flatten will return an empty sequence when given any non-sequential thing. That can sometimes hide a bug.

Here's another version that doesn't have that problem, and is faster as well.

(defn flatten2
  "Like `clojure.core/flatten` but better, stronger, faster.
  Takes any nested combination of sequential things (lists, vectors,
  etc.) and returns their contents as a single, flat, lazy sequence.
  If the argument is non-sequential (numbers, maps, strings, nil, 
  etc.), returns the original argument."
  {:static true}
  [x]
  (letfn [(flat [coll] 
                  (lazy-seq 
                   (when-let [c (seq coll)] 
                     (let [x (first c)] 
                       (if (sequential? x) 
                         (concat (flat x) (flat (rest c))) 
                         (cons x (flat (rest c))))))))]
    (if (sequential? x) (flat x) x)))

Note by tonsky

Actually, flatten on a vector returns list, not a collection:

user=> (flatten [1 [2 3]])
(1 2 3)

Note by slovic

lazy version is much slower than this one:

(defn my-flatten [l] 
  "free of StackOverflow problem, not lazy and much faster version of flatten."
(loop [l1 l, l2 `()]
  (cond
    (sequential? (first l1)) (recur (concat (first l1) (rest l1)) l2)
    (empty? l1) (reverse l2)
    :else (recur (rest l1) (cons (first l1) l2)))))

for complicated construction genereted by:

(defn gen-list-wird [c] (reduce (fn [a b] (list a b)) (map vector (range c) (map str (range c (* 2 c))))))

times are: core/flatten (260 msec) steveminer/flatten (135 msec) my-flatten (2 msec). This version is slower than steveminder`s version for flat and very nested structures with small number of items.

Note by miner

For a much faster implementation, use clojure.core.reducers/flatten (introduced in Clojure 1.5).

Note by afhammad

To only flatten one level, you can use (mapcat identity coll)

With flatten:

user=> (flatten [[[1]] [[2 3]]])
(1 2 3)

With mapcat identity:

user=> (mapcat identity [[[1]] [[2 3]]])
([1] [2 3])

Note by moskvo

afhammad, i think to flatten one level it may be useful

(apply concat coll)

Note by beluchin

does not flatten sets:

user=> (flatten [#{1}])
(#{1})

See also


Content from the matching ClojureDocs page, with authors credited on each contribution.