Hello i have a problem in ruby mine it says that my param isn't initialized can you help me? I need to sum all the subjects
class Student
attr_accessor :name, :english, :math, :science, :french, :pe
def initialize(name, english, math, science, french, pe)
@name = name
@english = english
@math = math
@science = science
@french = french
@pe = pe
end
def avg_sum_grades(param)
sum_of_subjcet_grades = students.map { |student| student.param }
end
students = [
student.new('brian', 3, 4, 5, 5, 6),
student.new('eric', 1, 3, 4, 5, 2),
student.new('jessica', 2, 1, 4, 5, 3),
student.new('agatha', 4, 4, 5, 3, 5),
student.new('alex', 2, 4, 5, 2, 5)
]
avg_sum_grades("english")
CodePudding user response:
You're trying to access a method based on a name passed into a method.
class Student
attr_accessor :name, :english, :math, :science, :french, :pe
def initialize(name, english, math, science, french, pe)
@name = name
@english = english
@math = math
@science = science
@french = french
@pe = pe
end
end
This is definitely possible by using a symbol with the #send
method.
bob = Student.new("Bob", 1, 2, 3, 4, 5)
bob.send(:pe)
# => 5
You're trying to do this on a group of Student
objects.
students = [
student.new('brian', 3, 4, 5, 5, 6),
student.new('eric', 1, 3, 4, 5, 2),
student.new('jessica', 2, 1, 4, 5, 3),
student.new('agatha', 4, 4, 5, 3, 5),
student.new('alex', 2, 4, 5, 2, 5)
]
So you could write:
def get_avg_grade(students, subject)
grades = students.map { |s| s.send(subject) }
grades.sum / grades.length
end
Which can be called: get_avg_grade(students, :math)
.
One more thing...
Given that you are just creating accessors for everything, you can really just write:
Student = Struct.new(:name, :english, :math, :science, :french, :pe)
CodePudding user response:
You will need the instance_variable_get
to get the instance variable as string.
class Student
attr_accessor :name, :english, :math, :science, :french, :pe
def initialize(name, english, math, science, french, pe)
@name = name
@english = english
@math = math
@science = science
@french = french
@pe = pe
end
end
@students = [
Student.new('brian', 3, 4, 5, 5, 6),
Student.new('eric', 1, 3, 4, 5, 2),
Student.new('jessica', 2, 1, 4, 5, 3),
Student.new('agatha', 4, 4, 5, 3, 5),
Student.new('alex', 2, 4, 5, 2, 5)
]
def avg_sum_grades(param)
sum_of_subjcet_grades = @students.sum{ |student| student.instance_variable_get("@#{param}") }
end
avg_sum_grades("english")
CodePudding user response:
class Student
attr_accessor :name, :english, :math, :science, :french, :pe
def initialize(name, english, math, science, french, pe)
@name = name
@english = english
@math = math
@science = science
@french = french
@pe = pe
end
# NOTE: make it a class method so we can call it on `Student` class;
# we have to have two arguments:
# an array of students and subject
def self.avg_sum_grades(students, subject)
students.map{|student| student.send(subject) }.sum / students.length
# or the short version
# students.sum(&subject.to_sym) / students.length
end
# NOTE: if you want to get some decimal points in the result
def self.avg_sum_grades_float(students, subject)
students.sum(&subject.to_sym) / students.length.to_f
end
end
students = [
Student.new('brian', 3, 4, 5, 5, 6),
Student.new('eric', 1, 3, 4, 5, 2),
Student.new('jessica', 2, 1, 4, 5, 3),
Student.new('agatha', 4, 4, 5, 3, 5),
Student.new('alex', 2, 4, 5, 2, 5)
]
Student.avg_sum_grades(students, "english") # => 2
Student.avg_sum_grades_float(students, "english") # => 2.4