Headers
Scautable supports flexible header handling using the HeaderOptions
enum. This allows fine-grained control over how headers are extracted or constructed from CSV input.
Available Options
TODO: Link scaladoc
AutoGenerated
Creates headers automatically:
import io.github.quafadas.table.*
import io.github.quafadas.scautable.HeaderOptions
inline val csvContent = "Name,Age\nFirst,Years\nAlice,30\nBob,24"
// csvContent: String = """Name,Age
// First,Years
// Alice,30
// Bob,24"""
val multiLine = CSV.fromString(csvContent, HeaderOptions.AutoGenerated)
// multiLine: CsvIterator[Tuple2["col_0", "col_1"], *:[String, *:[String, EmptyTuple]]] = non-empty iterator
multiLine.headers
// res0: Seq[String] = Vector("col_0", "col_1")
Useful when your CSV has no headers or you're working with raw tabular data.
Manual
Provides explicit header names:
import io.github.quafadas.table.*
import io.github.quafadas.scautable.HeaderOptions
val manual = CSV.fromString("1,2,3", HeaderOptions.Manual("a", "b", "c"))
// manual: CsvIterator[Tuple3["a", "b", "c"], *:[String, *:[String, *:[String, EmptyTuple]]]] = empty iterator
manual.headers
// res1: Seq[String] = ArraySeq("a", "b", "c")
manual.toSeq
// res2: Seq[NamedTuple[Tuple3["a", "b", "c"], *:[String, *:[String, *:[String, EmptyTuple]]]]] = List(
// ("1", "2", "3")
// )
FromRows
Combines multiple rows from the start of the file into multi-line headers. Also allows skipping initial metadata rows.
Behavior:
- Skips the first
dropFirst
rows (commonly used to ignore comments or metadata). - Then reads the next
merge
rows. - These rows are transposed so columns align.
- Each column is joined using
" "
to produce a final header.
Example:
import io.github.quafadas.table.*
import io.github.quafadas.scautable.HeaderOptions
inline val csvContent = "Name,Age\nFirst,Years\nAlice,30\nBob,24"
// csvContent: String = """Name,Age
// First,Years
// Alice,30
// Bob,24"""
val multiLine = CSV.fromString(csvContent, HeaderOptions.FromRows(merge = 2))
// multiLine: CsvIterator[Tuple2["Name First", "Age Years"], *:[String, *:[String, EmptyTuple]]] = non-empty iterator
multiLine.headers
// res4: Seq[String] = List("Name First", "Age Years")
This is useful when your data source encodes hierarchical or descriptive headers across multiple lines.
HeaderOptions.Default
Behavior
The default configuration is:
import io.github.quafadas.scautable.HeaderOptions
HeaderOptions.FromRows(merge = 1, dropFirst = 0)
// res5: HeaderOptions = FromRows(merge = 1, dropFirst = 0)
Which corresponds to the traditional single-row header handling.
Header deduplication
If you are in the situation where you have a large number of duplicate headers, consider de-duplication.
val csvDup: CsvIterator[("colA", "colA", "colA", "colB", "colC", "colA"), (String, String, String, String, String, String)] = CSV.resource("dups.csv")
val dedupCsv: CsvIterator[("colA", "colA_1", "colA_2", "colB", "colC", "colA_5"), (String, String, String, String, String, String)] = CSV.deduplicateHeader(csvDup)