Skip to content
Plugins (183)

csv

stable

CSV parser, serialiser, and query toolkit for reading, writing, filtering, sorting, and grouping tabular data with configurable delimiters.

use plugin csv::{parse, read_file, stringify, …}
14 functions Data Formats
Runs with the native Zolo host

Plugin snippets can be edited in the Playground, but native capabilities are executed locally with the Zolo CLI.

/ filter jk navigate Esc clear
Functions (14)
  1. parse Parse a CSV string into a table of rows
  2. read_file Read and parse a CSV file from disk
  3. stringify Serialise a table of rows to a CSV string
  4. write_file Write a table of rows to a CSV file
  5. parse_line Parse a single CSV line into fields
  6. count_rows Count the number of rows in a parsed table
  7. count_columns Count the number of columns in the first row
  8. get_column Extract all values for a named column
  9. filter_rows Filter rows by column value and operator
  10. sort_rows Sort rows by a column value
  11. unique_values Get distinct values for a column
  12. group_by Group rows by a column value
  13. get_headers Extract header names from the first row
  14. select_columns Project only specified columns from each row

From import to result

  1. 01Import only what you use
  2. 02Copy the smallest example
  3. 03Run it with the Zolo CLI

Overview

The csv plugin reads, writes, and queries comma-separated (and other delimited) data as plain Zolo tables. Parsing produces a table of rows keyed by 1-based integers, where each row is itself a table keyed by column name (or by 1-based index when headers are disabled). Because the parsed shape is just nested tables, the query helpers — filtering, sorting, grouping, projection — all operate on the same value and compose freely. Reach for it whenever you need to load tabular data from a string or file, transform it, and serialise it back out, all without an external dependency or an explicit schema.

Common patterns

Load a file, narrow it down, and write the result back:

use plugin csv::{read_file, filter_rows, select_columns, write_file}

let rows = read_file("/data/users.csv")
let adults = filter_rows(rows, "age", "gt", 18)
let slim = select_columns(adults, #{1: "name", 2: "email"})
write_file("/tmp/adults.csv", slim)

Parse a string, then rank and report on it:

use plugin csv::{parse, sort_rows, count_rows}

let rows = parse("name,score\nBob,87\nAlice,95\nCarol,92")
let ranked = sort_rows(rows, "score", false)
print("{count_rows(ranked)} players, top is {ranked[1]["name"]}")

Summarise a column by grouping distinct values:

use plugin csv::{parse, unique_values, group_by}

let rows = parse("dept,name\nEng,Alice\nHR,Bob\nEng,Carol")
print("departments: {#unique_values(rows, "dept")}")

let groups = group_by(rows, "dept")
print("first dept {groups[1]["key"]} has {#groups[1]["rows"]} people")

Parse a CSV string into a table of rows

Parses a CSV string and returns a table of row tables. With headers (default), each row is keyed by column name. Without headers, keys are 1-based integers. config is optional and accepts headers (bool) and delimiter (string).

use plugin csv::{parse}

let data = "name,age,city\nAlice,30,NYC\nBob,25,LA"
let rows = parse(data)
print(rows[1]["name"])
print(rows[2]["age"])
use plugin csv::{parse}

let tsv = "Alice\t30\nBob\t25"
let rows = parse(tsv, #{"headers": false, "delimiter": "\t"})
print(rows[1][1])

Read and parse a CSV file from disk

Reads a CSV file from path and returns the same structure as parse. config is optional and accepts the same options as parse.

use plugin csv::{read_file}

let rows = read_file("/data/users.csv")
print("loaded {#rows} rows")
print(rows[1]["email"])

Serialise a table of rows to a CSV string

Serialises a table of row tables to a CSV string. Writes a header row from the string keys of the first row, then one data row per entry.

use plugin csv::{stringify}

let rows = #{
  1: #{"name": "Alice", "age": "30"},
  2: #{"name": "Bob", "age": "25"}
}
let csv = stringify(rows)
print(csv)

Round-tripping is lossless for shape: parse a string, transform it, and write it back out with a custom delimiter.

use plugin csv::{parse, sort_rows, stringify}

let rows = parse("name,age\nBob,25\nAlice,30")
let sorted = sort_rows(rows, "name", true)
print(stringify(sorted, #{"delimiter": ";"}))

Write a table of rows to a CSV file

Serialises rows to CSV and writes the result to the file at path.

use plugin csv::{write_file}

let rows = #{
  1: #{"product": "Widget", "price": "9.99"},
  2: #{"product": "Gadget", "price": "19.99"}
}
write_file("/tmp/products.csv", rows)

Parse a single CSV line into fields

Parses a single CSV line and returns a table of field values with 1-based integer keys. delimiter defaults to ",".

use plugin csv::{parse_line}

let fields = parse_line('Alice,"New York",30')
print(fields[1])
print(fields[2])

Count the number of rows in a parsed table

Returns the number of rows in a parsed CSV table.

use plugin csv::{parse, count_rows}

let rows = parse("a,b\n1,2\n3,4\n5,6")
print("rows: {count_rows(rows)}")

Count the number of columns in the first row

Returns the number of columns in the first row of a parsed CSV table.

use plugin csv::{parse, count_columns}

let rows = parse("id,name,email,age\n1,Alice,[email protected],30")
print("columns: {count_columns(rows)}")

Extract all values for a named column

Extracts all values for the named column and returns them as a 1-based table of strings.

use plugin csv::{parse, get_column}

let rows = parse("name,score\nAlice,95\nBob,87\nCarol,92")
let scores = get_column(rows, "score")
print(scores[1])
print(scores[2])

Filter rows by column value and operator

Returns only rows where the column matches the condition. Supported operators: "eq", "neq", "gt", "lt", "contains". Numeric comparisons are performed when both sides parse as floats.

use plugin csv::{parse, filter_rows}

let rows = parse("name,age\nAlice,30\nBob,17\nCarol,25")
let adults = filter_rows(rows, "age", "gt", 18)
print("adults: {#adults}")

let search = filter_rows(rows, "name", "contains", "li")
print(search[1]["name"])

Filters return the same row shape, so they chain — apply one condition, then another, to narrow the set step by step.

use plugin csv::{parse, filter_rows}

let rows = parse("name,dept,age\nAlice,Eng,30\nBob,Eng,17\nCarol,HR,40")
let eng = filter_rows(rows, "dept", "eq", "Eng")
let senior_eng = filter_rows(eng, "age", "gt", 18)
print("senior engineers: {#senior_eng}")

Sort rows by a column value

Returns rows sorted by the given column. Numeric sorting is used when values parse as numbers; otherwise lexicographic. ascending defaults to true.

use plugin csv::{parse, sort_rows}

let rows = parse("name,score\nBob,87\nAlice,95\nCarol,92")
let ranked = sort_rows(rows, "score", false)
print("top scorer: {ranked[1]["name"]}")

When a column holds non-numeric text, sorting falls back to lexicographic order, so the same call alphabetises names ascending.

use plugin csv::{parse, sort_rows}

let rows = parse("name,score\nCarol,92\nAlice,95\nBob,87")
let alpha = sort_rows(rows, "name", true)
print(alpha[1]["name"])
print(alpha[2]["name"])

Get distinct values for a column

Returns a table of distinct values (in first-seen order) for the named column.

use plugin csv::{parse, unique_values}

let rows = parse("city\nNYC\nLA\nNYC\nChicago\nLA")
let cities = unique_values(rows, "city")
print("unique cities: {#cities}")

Group rows by a column value

Groups rows by the named column. Returns a table of {key, rows} entries, one per distinct value, preserving insertion order.

use plugin csv::{parse, group_by}

let rows = parse("dept,name\nEng,Alice\nHR,Bob\nEng,Carol")
let groups = group_by(rows, "dept")
print("groups: {#groups}")
print("first group key: {groups[1]["key"]}")
print("members: {#groups[1]["rows"]}")

Each group's rows is itself a parsed CSV table, so the query helpers work on a single group just as they do on the whole dataset.

use plugin csv::{parse, group_by, count_rows}

let rows = parse("dept,name\nEng,Alice\nHR,Bob\nEng,Carol\nEng,Dan")
let groups = group_by(rows, "dept")
for g in groups {
  print("{g["key"]}: {count_rows(g["rows"])}")
}

Extract header names from the first row

Extracts the column header names from the first row of a parsed CSV table. Returns a 1-based table of strings.

use plugin csv::{parse, get_headers}

let rows = parse("id,name,email\n1,Alice,[email protected]")
let headers = get_headers(rows)
print(headers[1])
print(headers[2])
print(headers[3])

Project only specified columns from each row

Projects only the specified columns from each row. columns is a table of column name strings. Columns not in the list are dropped.

use plugin csv::{parse, select_columns}

let rows = parse("id,name,email,age\n1,Alice,[email protected],30")
let slim = select_columns(rows, #{1: "name", 2: "email"})
print(slim[1]["name"])
print(slim[1]["email"])

Global index

Find your way through Zolo

Try an idea

Start here

9 results

9 results

en