Estou começando com Ruby, e estou tentando fazer uma classe que leia um arquivo em formato csv
, disposto em linhas e colunas. Porém, não estou conseguindo pegar cada uma das linhas e colunas separadamente. Alguém saberia me dizer como fazer isso? Olhei na documentação, mas apanhei um pouco confuso.
Meu código está retornando a seguinte saída.
["nome", "idade", "nascimento", "telefone"]
["carlos", "15", "01/01", "999999999"]
["joao", "16", "01/02", "888888888"]
["teste", "errada", "02/03", "444444444"]
["paulo", "18", "01/04", "55555555"]
Código:
require 'csv'
CSV.foreach("/arquivo.csv", col_sep: ",") do |row|
puts row.inspect
end
Eu não manjo nada de ruby, mas, sei que arquivos com a extensão CSV até podem ser vistos como um monte de linhas e colunas. Porém, até pelo significado da sigla (Comma Separated Values ou valores separados por vírgulas) acho difícil você conseguir ler estes valores isoladamente.
Se fosse em java eu faria algo como
//Código até aqui
Scanner sc = new Scanner(new File("c:\\caminho\\ate\\o\\arquivo\\arquivo.csv");
while(sc.hasNextLine()) {
String linha = sc.nextLine();
String[] colunas = linha.split(",");
//Faz o que quiser com cada coluna.
}
Só lembrando que o split(",") vai quebrar a linha de acordo com a quantidade de vírgulas.
Enfim, esse seria eu, em java.
Eu não consegui entender bem o que você quer dizer com “pegar cada uma das linhas e colunas separadamente”. Se trata disso por acaso?
["carlos", "joao", "teste", "paulo"] // nomes
["15", "16", "errada", "18"] // idades
// etc
Se for, acho que precisa manipular o resultado das rows, produzindo o resultado esperado.
Se puder, diga qual é saída que você quer ter como retorno.
Se você indicar que a primeira linha possui os headers, você pode acessar cada coluna diretamente no objeto row:
require 'csv'
CSV.foreach('./arquivo.csv', col_sep: ",", headers: true) do |row|
puts row['nome']
puts row['telefone']
end
Então, eu consegui resolver o problema da seguinte maneira:
lines = File.readlines('./sample.csv')
.map { |line| line.split(',') }
E acessei as linhas e colunas utilizando o próprio índice. Funcionou, porém, não sei se é a forma correta de fazer em ruby.
for i in 0..lines.length()-1
valores = lines[i][6].downcase
É isso mesmo, dessa maneira.
Legal que você resolveu!
Pra ficar mais “Ruby” isso, poderia utilizar métodos do módulo Enumerable.
No teu caso acho que um reduce
daria mais jeito, o código ficaria mais clean e funcional.
# Não vejo isso sendo muito utilizado mas gosto do "pipeline" way,
# encadeando métodos (funções) de forma funcional.
File
.readlines('./sample.csv')
.map { |line| line.split(',') }
.reduce([]) { |acc, column| acc += column[6].downcase }
Seria algo assim, eu não testei aqui, tem que testar e ver se rola no teu caso talvez com algumas adaptações.