How do I flatten nested collections and optionals in EK9?

← Collections and Data Structures · Ref: Q123

EK9 uses | flatten in stream pipelines to collapse nested structures into flat sequences. This is commonly used after group operations that produce lists of lists.

FLATTEN LIST OF LIST

After a group operation, you have List of List of T. Flatten merges into List of T:

  cat grouped | flatten | collect as List of String

Each inner list's elements are emitted in order.

FLATTEN IN PIPELINES

Flatten typically appears after group and map stages:

  cat items
    | sort by key
    | group by category
    | map by transform
    | flatten
    | collect as List of Item

This is the standard group-process-flatten pattern.

WHEN FLATTEN IS NEEDED

Any pipeline operation that wraps results in an extra layer needs flatten to unwrap:

  group by produces List of List of T from List of T
  map after group produces List of List of U from List of List of T

Flatten removes exactly one level of nesting.

FLATTEN WITH OUTPUT

Pipe flattened results directly to stdout:

  cat groupedItems | flatten > stdout

Each element prints on its own line.

See Q85 for Optional stream patterns. See Q89 for basic stream pipelines. See Q124 for group by that creates nested lists.

Example

defines module qa.collections.flatten

  defines function

    firstChar() as pure
      -> word as String
      <- rtn as String: $#<word

  defines program

    FlattenDemo()
      stdout <- Stdout()

      words <- ["apple", "avocado", "banana", "blueberry", "cherry", "cranberry"]

      // === GROUP THEN FLATTEN ===

      // Group by first character, then flatten back
      grouped <- cat words | sort | group by firstChar | collect as List of List of String
      stdout.println(`Grouped: ${grouped}`)

      flat <- cat grouped | flatten | collect as List of String
      stdout.println(`Flattened: ${flat}`)

      // === FLATTEN WITH DIRECT OUTPUT ===

      cat grouped | flatten > stdout

      // === NESTED LIST CREATION AND FLATTEN ===

      nested <- [
        ["one", "two"],
        ["three", "four"],
        ["five", "six"]
        ]

      allItems <- cat nested | flatten | collect as List of String
      stdout.println(`All items: ${allItems}`)

Common mistakes

E50060 — EK9 has no flatten() method on collections. Use | flatten in a stream pipeline to collapse nested structures. The pipeline form is: cat nested | flatten | collect as List of T. See ek9 -h E50060 for details.

Incorrect:

flat <- grouped.flatten()

Correct:

flat <- cat grouped | flatten | collect as List of String

E50001 — Flatten takes no function argument — it simply unwraps the nested structure. Unlike Java's flatMap() which combines map and flatten, EK9 separates these operations. See ek9 -h E50001 for details.

Incorrect:

cat nested | flatten myFunction | collect as List of String

Correct:

cat nested | flatten | collect as List of String

E07830 — After flattening List of List of String, the stream type is String. Collecting into List of Date fails because String and Date are incompatible types. The collect target must match the stream type. See ek9 -h E07830 for details.

Incorrect:

allItems <- cat nested | flatten | collect as List of Date

Correct:

allItems <- cat nested | flatten | collect as List of String

E50060 — EK9 does not have toString(). Use string interpolation or the $ operator. See ek9 -h E50060 for details.

Incorrect:

stdout.println(flat.toString())

Correct:

stdout.println(`Flattened: ${flat}`)

E50060 — EK9 does not have Java-style .stream().collect() method chains. Use pipe syntax: 'cat items | collect as Type'. See ek9 -h E50060 for details.

Incorrect:

stdout.println(allItems.stream().collect())

Correct:

stdout.println(`All items: ${allItems}`)
Other ways to ask this
  • How does the flatten pipeline operation work in EK9?
  • How do I merge nested lists into a single list in EK9?
  • How do I flatten a list of lists in EK9?
  • What is the EK9 equivalent of flatMap?

Coming from another language?

Java: stream.flatMap(Collection::stream) or Stream.concat(). Python: itertools.chain.from_iterable() or [item for sublist in nested for item in sublist]. JavaScript: array.flat() or array.flatMap(). Rust: iter.flatten() or iter.flat_map(). Go: manual nested loops. EK9: | flatten in pipeline after group or nested operations, removes one level of nesting.

Keywords: collapse, data-structure, flatten, stream, flat, optional, pipeline, flatMap, nested, collection, list, concatMap, unwrap, merge, group