vendor/csv Vendor

Ler e escrever dados CSV a partir de strings ou arquivos, com aspas e escapes corretos.

import vendor/csv

O parser lida com campos entre aspas, aspas escapadas (""), quebras de linha internas e retornos de carro finais. Toda função de leitura aceita argumentos opcionais graças aos padrões por cláusula da Bern.

Formato dos dados

As linhas são devolvidas como um objeto indexado pelo número da linha ("0", "1", …). Com cabeçalhos ativados (o padrão), cada linha é, ela mesma, um objeto indexado pelos nomes dos cabeçalhos; sem cabeçalhos, cada linha é uma lista simples de campos.

-- com cabeçalhos (padrão)
#{ "0": #{ name: "Ana", age: "30" }#, "1": #{ name: "Bob", age: "25" }# }#

-- sem cabeçalhos / parse_csv_rows
#{ "0": ["name", "age"], "1": ["Ana", "30"], "2": ["Bob", "25"] }#

Leitura & parsing

parse_csv(conteúdo, delimitador=",", tem_cabeçalho=true, pular_linhas_vazias=true) → objeto

Faz parse de texto CSV. Com cabeçalhos ligados, devolve as linhas como objetos indexados pelo cabeçalho.

csv = "name,age\nAna,30\nBob,25"
rows = parse_csv(csv)
rows["0"]["name"]
-- Saída: "Ana"
rows["1"]["age"]
-- Saída: "25"
parse_csv_rows(conteúdo, delimitador=",", pular_linhas_vazias=true) → objeto

Faz parse em linhas cruas (listas de campos), sem aplicar cabeçalhos.

rows = parse_csv_rows("a,b\n1,2")
rows["0"]
-- Saída: ["a", "b"]
rows["1"]
-- Saída: ["1", "2"]
read_csv(nome_arquivo, delimitador=",", tem_cabeçalho=true, pular_linhas_vazias=true) → objeto

Lê um arquivo e o parseia em um passo (a versão de arquivo do parse_csv).

rows = read_csv("people.csv")
rows["0"]["name"]
-- Saída: (nome da primeira pessoa)
read_csv_rows(nome_arquivo, delimitador=",", pular_linhas_vazias=true) → objeto

Lê um arquivo em linhas cruas (a versão de arquivo do parse_csv_rows).

rows = read_csv_rows("data.tsv", "\t")
rows["0"]
-- Saída: (primeira linha como lista de campos)

Escrita

write_csv_from_list(cabeçalhos, lista_dados, nome_arquivo, delimitador=",") → void

Escreve um conjunto lista-de-listas, prefixado pela linha de cabeçalho. Campos são colocados entre aspas automaticamente quando necessário.

write_csv_from_list(
    ["name", "age"],
    [["Ana", "30"], ["Bob", "25"]],
    "out.csv"
)
-- Escreve:
-- name,age
-- Ana,30
-- Bob,25
write_csv_from_objects(cabeçalhos, objeto_dados, nome_arquivo, delimitador=",") → void

Escreve um objeto indexado de objetos-linha, puxando os campos na ordem de cabeçalho informada.

people = #{
    "0": #{ name: "Ana", age: "30" }#,
    "1": #{ name: "Bob", age: "25" }#
}#
write_csv_from_objects(["name", "age"], people, "out.csv")

Juntando tudo

Um pipeline completo: ler um arquivo, transformar uma coluna e escrever o resultado de volta. Aqui lemos pessoas, incrementamos a idade de todas e salvamos:

Ler → transformar → escrever

import core
import strings
import vendor/csv

rows = parse_csv("name,age\nAna,30\nBob,25")

-- monta as novas linhas como listas, na ordem do cabeçalho
out = []
loop i : [0..(length(keys(rows)) - 1)] do
    r = rows["" + i]
    next_age = to_int(r["age"]) + 1
    out = out <> [[r["name"], from_int(next_age)]]
end

write_csv_from_list(["name", "age"], out, "people_aged.csv")
-- people_aged.csv agora contém Ana,31 e Bob,26

E uma agregação rápida direto das linhas parseadas, com core:

Totalizando uma coluna numérica

import core
import vendor/csv

rows = parse_csv("item,price\npen,3\nbook,12\nlamp,20")

total = 0
loop i : [0..(length(keys(rows)) - 1)] do
    total = total + to_int(rows["" + i]["price"])
end

total
-- Saída: 35