Ruby Quiz is Back - Challenge #1 - Read Comma-Separated Values (CSV) from the "Real World"

Hello,
   sorry for the false start of the Ruby Quiz. The Ruby Quiz is now
back for real.

  Challenge #1 - Read Comma-Separated Values (CSV) from the "Real World"

   Let's use the test.csv [1] file from Apache Commons CSV Reader.
The challenge: Code a parse method that passes the RubyQuizTest :-).
Start from scratch or, yes, use any library / gem you can find.

def parse( txt )
  ...
end

To qualify for solving the code challenge / puzzle you must pass the test:

```
require 'minitest/autorun'

class RubyQuizTest < MiniTest::Test

  def test_parse

    records = [["A", "B", "C", "D"],
              ["a", "b", "c", "d"],
              ["e", "f", "g", "h"],
              [" i ", " j ", " k ", " l "],
              ["", "", "", ""],
              ["", "", "", ""]]

    assert_equal records, parse( <<TXT )
A,B,C,"D"
# plain values
a,b,c,d
# spaces before and after
e ,f , g,h
# quoted: with spaces before and after
" i ", " j " , " k "," l "
# empty values

···

,
# empty quoted values
"","","",""
# 3 empty lines

# EOF on next line
TXT

  end # method test_parse
end # class RubyQuizTest
```

Post your code snippets here on the "official" Ruby Quiz Channel,
that is, the ruby-talk mailing list :-).

Happy hacking and data wrangling with Ruby.

[1]: https://github.com/apache/commons-csv/blob/master/src/test/resources/CSVFileParser/test.csv

Dear Quizmaster,

Are there general guidelines like for the first Ruby Quiz (
http://rubyquiz.com/\)?

Anyway, here is my brief entry.

···

#
# A simple solution using core String and Regexp features.
#
def parse( txt )
  txt.each_line.map do |line|
    next if line =~ /^#/ || line =~ /^\s+$/
    line.strip.split(/\s*,\s*/, -1).map do |field|
      field.sub(/^(['"])(.*)\1$/, '\\2')
    end
  end.compact
end

Cheers,
Dave

On Mon, Oct 29, 2018 at 2:53 AM Gerald Bauer <gerald.bauer@gmail.com> wrote:

Hello,
   sorry for the false start of the Ruby Quiz. The Ruby Quiz is now
back for real.

  Challenge #1 - Read Comma-Separated Values (CSV) from the "Real World"

   Let's use the test.csv [1] file from Apache Commons CSV Reader.
The challenge: Code a parse method that passes the RubyQuizTest :-).
Start from scratch or, yes, use any library / gem you can find.

def parse( txt )
  ...
end

Hello,

    Fantastic. Thanks for the great and brief example.

Dear Quizmaster,

Are there general guidelines like for the first Ruby Quiz (http://rubyquiz.com/\)?

   I'm Gerald - just a regular ruby-talk poster - no need for titles
:-). Welcome. Thanks for joining in.

Are there general guidelines like for the first Ruby Quiz (http://rubyquiz.com/\)?

   The new Ruby Quiz website is at Planet Ruby (
GitHub - planetruby/quiz: Ruby Quiz is a fortnightly programming challenge for Ruby programmers. A new Ruby Quiz is sent to the Ruby Talk mailing list once every two weeks. Join us. )

    For now the only rule is that you have to pass the RubyQuizTest to qualify.

    Cheers. Prost.

Hello,
    For inspiration here's a snippet posted on the reddit ruby thread
[1]. Thanks to Paul.

class CSV include Mealy initial_state(:start) { @line = []; @text = ''
} read(state: :start, on: "\n") transition(from: :start, to: :comment,
on: '#') transition(from: :comment, to: :start, on: "\n") read(state:
:comment) transition from: [:normal, :start], to: :quote, on: '"'
transition from: :quote, to: :normal, on: '"' transition(from: :start,
:normal, on: ' ') transition(from: :start, to: :normal) { |c| @text <<
c } transition(from: :normal, to: :start, on: "\n") do emit @line <<
@text; @line = []; @text = '' end read state: :normal, on: ' '
read(state: :normal, on: ',') { @line << @text; @text = '' }
read(state: [ :normal, :quote ]) { |c| @text << c } finish { emit
@line unless @line.empty? } end def parse(text)
CSV.new.run(text.chars).entries end

Happy hacking and data wrangling with Ruby.

[1] https://old.reddit.com/r/ruby/comments/9sbbt3/ruby_quiz_is_back_a_fortnightly_programming/

···

to: :normal, on: ',') { @line << '' } transition(from: :start, to:

Hello,
   sorry for the "minified" code snippet version for the Ruby Quiz #1.
Trying again (looks good in the email preview):

···

---
class CSV
  include Mealy

  initial_state(:start) { @line = []; @text = '' }

  read(state: :start, on: "\n")

  transition(from: :start, to: :comment, on: '#')
  transition(from: :comment, to: :start, on: "\n")
  read(state: :comment)

  transition from: [:normal, :start], to: :quote, on: '"'
  transition from: :quote, to: :normal, on: '"'

  transition(from: :start, to: :normal, on: ',') { @line << '' }
  transition(from: :start, to: :normal, on: ' ')
  transition(from: :start, to: :normal) { |c| @text << c }
  transition(from: :normal, to: :start, on: "\n") do
    emit @line << @text; @line = []; @text = ''
  end

  read state: :normal, on: ' '
  read(state: :normal, on: ',') { @line << @text; @text = '' }

  read(state: [ :normal, :quote ]) { |c| @text << c }

  finish { emit @line unless @line.empty? }
end

def parse(text)
  CSV.new.run(text.chars).entries
end
---

  Happy hacking and data wrangling with Ruby.