H
Hugh Sasse
I have been splitting a comma separated values file, and putting
some of the values into an Student class, simply a collection of strings,
so that I can build a database table from them:
require 'set'
class Student
attr_accessor :forename, :surname, :birth_dt,
icture, :coll_status
def initialize(forename0, surname0, birth_dt0,
picture0, coll_status0)
@forename = forename0
@surname = surname0
@birth_dt = birth_dt0
@picture = picture0
puts "in student.new() picture is #{picture0.inspect}, @picture is #{@picture.inspect} " if $debug
@coll_status = coll_status0
end
def eql?(other)
# if self.forename == "John" and other.forename == "John"
debug = true
# end
res = [:forename, :surname, :birth_dt, icture, :coll_status].all? do |msg|
print "#{self.send(msg)} == #{(other.send(msg))} gives #{self.send(msg) == (other.send(msg))}" if debug
self.send(msg) == (other.send(msg))
end
return res
end
def to_s
"#{@surname}, #{@forename}, #{@birth_dt}, #{@picture}, #{@coll_status}"
end
end
And in the body of my program I read the records in from the csv and
add the students if they are new. They tend to be clustered in the
input, hence the last_student test.
class TableMaker
INPUT = "hugh.csv"
ACCEPTED_MODULES = /^\"TECH(100[1-7]|200\d|201[01]|300\d|301[0-2])/
# Read in the database and populate the tables.
def initialize(input=INPUT)
@students = Set.new()
# [...]
open(input, 'r') do |infp|
while record = infp.gets
record.chomp!
puts "record is #{record}"
forename, surname, birth_dt, institution_id, aos_code,
various, other, fields,
picture, coll_status, full_desc = record.split(/\s*\|\s*/)
next unless aos_code =~ ACCEPTED_MODULES
puts "from record, picture is [#{picture.inspect}]." if $debug
# Structures for student
student = Student.new(forename, surname, birth_dt, picture, coll_status)
if student == last_student
student = last_student
else
student.freeze
# Avoid duplicates
unless @students.include? student
@students.add student
end
last_student = student
end
# [...]
end
end
end
# [...]
end
This being a Set I don't really need the call to include? now, but
it's there (from when I was using a hash for this).
I find two things that seem odd to me:
1. eql? is never getting called, despite include?.
2. I end up with duplicate students.
Sets *can't* hold duplicates, and include depends on eql? for Sets.
So what's going on? I have checked, and the duplicate students seem to
have identical strings, so I wrote the eql? to be sure.
I bet this will be a self.kick(self) reason, but I can't see it yet.
Thank you,
Hugh
some of the values into an Student class, simply a collection of strings,
so that I can build a database table from them:
require 'set'
class Student
attr_accessor :forename, :surname, :birth_dt,
icture, :coll_status
def initialize(forename0, surname0, birth_dt0,
picture0, coll_status0)
@forename = forename0
@surname = surname0
@birth_dt = birth_dt0
@picture = picture0
puts "in student.new() picture is #{picture0.inspect}, @picture is #{@picture.inspect} " if $debug
@coll_status = coll_status0
end
def eql?(other)
# if self.forename == "John" and other.forename == "John"
debug = true
# end
res = [:forename, :surname, :birth_dt, icture, :coll_status].all? do |msg|
print "#{self.send(msg)} == #{(other.send(msg))} gives #{self.send(msg) == (other.send(msg))}" if debug
self.send(msg) == (other.send(msg))
end
return res
end
def to_s
"#{@surname}, #{@forename}, #{@birth_dt}, #{@picture}, #{@coll_status}"
end
end
And in the body of my program I read the records in from the csv and
add the students if they are new. They tend to be clustered in the
input, hence the last_student test.
class TableMaker
INPUT = "hugh.csv"
ACCEPTED_MODULES = /^\"TECH(100[1-7]|200\d|201[01]|300\d|301[0-2])/
# Read in the database and populate the tables.
def initialize(input=INPUT)
@students = Set.new()
# [...]
open(input, 'r') do |infp|
while record = infp.gets
record.chomp!
puts "record is #{record}"
forename, surname, birth_dt, institution_id, aos_code,
various, other, fields,
picture, coll_status, full_desc = record.split(/\s*\|\s*/)
next unless aos_code =~ ACCEPTED_MODULES
puts "from record, picture is [#{picture.inspect}]." if $debug
# Structures for student
student = Student.new(forename, surname, birth_dt, picture, coll_status)
if student == last_student
student = last_student
else
student.freeze
# Avoid duplicates
unless @students.include? student
@students.add student
end
last_student = student
end
# [...]
end
end
end
# [...]
end
This being a Set I don't really need the call to include? now, but
it's there (from when I was using a hash for this).
I find two things that seem odd to me:
1. eql? is never getting called, despite include?.
2. I end up with duplicate students.
Sets *can't* hold duplicates, and include depends on eql? for Sets.
So what's going on? I have checked, and the duplicate students seem to
have identical strings, so I wrote the eql? to be sure.
I bet this will be a self.kick(self) reason, but I can't see it yet.
Thank you,
Hugh