使用first_name,last_name和email属性为每一行构建一个Person对象。这个人员列表应该封装在一个类中,该类可以执行不同属性返回唯一的操作,即:people.unique_by_first_name。人物对象也应该是Enumberable。
#!/usr/bin/env ruby
class Person
attr_accessor :first_name, :last_name, :email
def self.unique_by_first_name(people_array)
people_array.uniq{ |x| x.first_name } # see result below
end
def self.import_data
people_array = Array.new
file = DATA.read
file.each_line do |line|
person = Person.new
fields = line.split(',')
fields.each_with_index do |field, i|
if field.include? '@'
person.email = field.to_s.strip
fields.delete_at(i)
elsif field.empty?
fields.delete_at(i)
else
person.first_name = fields[0].to_s.strip
person.last_name = fields[1].to_s.strip
end
end
people_array.push(person)
end
Person.unique_by_first_name(people_array)
end
end
Person.import_data
__END__
John,Smith,john@foo.com
james@data.net,James
Phillip,Jones,phil@msn.com
,Irene,Smith
Robert,Chorley,rob@foo.com,
emma@hotmail.com,Emma,
David,Smith
james@game.net,James,Bond
james@game.net,James,Bond
[#<Person:0x007fd30228fdc0 @email="john@foo.com", @first_name="John", @last_name="Smith">,
#<Person:0x007fd30228f870 @email="james@data.net">,
#<Person:0x007fd30228f438 @email="phil@msn.com", @first_name="Phillip", @last_name="Jones">,
#<Person:0x007fd30228ea60 @first_name="Irene", @last_name="Smith">,
#<Person:0x007fd30228e420 @email="rob@foo.com", @first_name="Robert", @last_name="Chorley">,
#<Person:0x007fd3022879e0 @email="emma@hotmail.com", @first_name="Emma", @last_name="">,
#<Person:0x007fd302286680 @first_name="David", @last_name="Smith">,
#<Person:0x007fd302285e38 @email="james@game.net", @first_name="James", @last_name="Bond">]
上面的代码产生以下结果^。你们对如何改进这种逻辑有任何建议吗?
答案 0 :(得分:1)
为了让您在Person
课程中访问这些属性,您需要添加:
attr_reader :first_name, :last_name, :email
到您班级的顶端
像这样:
class Person
attr_reader :first_name, :last_name, :email
def initialize(first_name, last_name, email)
first_name = first_name
last_name = last_name
email = email
end
现在您可以在对象上调用x.first_name,因为您明确允许程序读取它。这是一个非常有名的SO answer。