如何在 ruby 中使用方法参数作为变量

How to use Method param as variable in ruby

你好,我的 ruby 有一个问题,它说我的参数没有初始化,你能帮我吗?我需要对所有科目求和

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")

您正在尝试访问基于传递给方法的 名称 的方法。

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

这绝对可以通过使用带有 #send 方法的符号来实现。

bob = Student.new("Bob", 1, 2, 3, 4, 5)
bob.send(:pe)
# => 5

您正在尝试对一组 Student 个对象执行此操作。

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 get_avg_grade(students, subject)
  grades = students.map { |s| s.send(subject) }
  grades.sum / grades.length
end

可以调用:get_avg_grade(students, :math).

还有一件事...

鉴于您只是为所有内容创建访问器,您真的可以只写:

Student = Struct.new(:name, :english, :math, :science, :french, :pe)

您将需要 instance_variable_get 来获取字符串形式的实例变量。

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")

我的答案的显着特点是它不要求所有学生都选修过相同的课程。

我想到下面的例子来创建classStudent的实例:

Student.new('eric', english: 1, math: 3, french: 5, pe: 2),

请注意 Eric 尚未注册科学。


class Student
  attr_accessor :name, :grades
  def initialize(name, **grades)
    @name = name
    @grades = grades
  end
end
def avg_grade(students, subject)
  avg(students.filter_map do |student|
    student.grades[subject] if student.grades.key?(subject)
  end)
end
def avg(arr)
  arr.sum.fdiv(arr.size).round(1)
end

参见 Double-Splat, Enumerable#filter_map and Numeric#fdiv and Numeric#round


让我们创建一些学生。

students = [
  Student.new('brian', english: 3, math: 4, science: 5, french: 5, pe: 6),
  Student.new('eric', english: 1, math: 3, french: 5, pe: 2),
  Student.new('jessica', math: 1, science: 4, french: 5, pe: 3),
  Student.new('agatha', english: 4, science: 5, french: 3, pe: 5),
  Student.new('alex', english: 2, math: 4, french: 2, pe: 5)
]

让我们看看我们有什么。

students.each { |student| puts "@name = #{student.name}, @grades = #{student.grades}" }
@name = brian, @grades = {:english=>3, :math=>4, :science=>5, :french=>5, :pe=>6}
@name = eric, @grades = {:english=>1, :math=>3, :french=>5, :pe=>2}
@name = jessica, @grades = {:math=>1, :science=>4, :french=>5, :pe=>3}
@name = agatha, @grades = {:english=>4, :science=>5, :french=>3, :pe=>5}
@name = alex, @grades = {:english=>2, :math=>4, :french=>2, :pe=>5}

现在按学科计算平均成绩。为此,我们首先构建一个由至少一名学生选修的所有科目组成的数组:

subjects = students.reduce([]) { |subs, student| subs | student.grades.keys }
  #=> [:english, :math, :science, :french, :pe]

然后按学科显示平均成绩:

subjects.each { |subject| puts "#{subject}: #{avg_grade(students, subject)}" }
english: 2.5
math: 3.0
science: 4.7
french: 4.0
pe: 4.2

参见 Array#|


即使所有学生都选修相同的五门科目,也可以说

Student.new('brian', english: 3, math: 4, science: 5, french: 5, pe: 6)

会比

少error-prone
Student.new('brian', 3, 4, 5, 5, 6)

据了解,成绩分别针对英语、数学、科学、法语和 PE。当然,如果成绩是从外部来源以这种格式提供的,那么就无法选择如何表达论点。