Ruby:不同数量的 case 语句
Ruby: Varying Number of case statemnts
我目前正在 Ruby 编写一个自动化的团队组建程序,它根据学生的技能组成不同的团队。该技能来自前一年学生的成绩(即 [0;100] 范围内的整数)。我已经实现了一个默认版本的成绩到技能转换方法,其中成绩根据以下阈值转换为技能
[0;39] => 1
[40;49] = > 2
[50;59] = > 3
[60;69] = > 4
[70;79] = > 5
[80;100] = > 6
这是通过 case/when 语句实现的
但是,该程序将根据教师的使用而设计,我想让教师能够对如何衡量学生的技能做出自己的解释(例如,他可能希望拥有更少或更多的技能组或给定技能组的不同阈值)。
我的想法是他将能够以哈希的形式将它们作为命名参数传递,将 2 值数组作为键(成绩阈值)和整数作为值(技能),但是我正在努力思考一个巧妙的方法来实现它。
是否有可能实现可变数量的 when 语句,其中每个语句负责给定的技能(比如将它们放在某种循环中?)。或者你能想到任何其他方法可以解决这个问题吗?
非常感谢您的帮助!
给定这样的结构:
values = {
0..39 => 1,
40..49 => 2,
50..59 => 3,
60..69 => 4,
70..79 => 5,
80..100 => 6
}
您可以使用 find
来获取符合特定条件的第一个条目:(假设范围不重叠并且没有 "holes" – 您可能想要验证提供的数据第一)
grade = 52
range, skill = values.find { |r, v| r.cover?(grade) }
range #=> 50..59
skill #=> 3
使用 bsearch
比 find
性能更高,只要你能保证数组有序 – O(log n)
vs find
的 O(n)
–没有任何额外的内存支出(堆栈框架除外,呵呵)。此外,由于您的范围(大概)是连续的,它们之间没有任何空洞,您可以只指定阈值。
因此,如果您的索引始终为“1..N”,则此方法可行:
def grade(points, scale)
scale.bsearch_index { |x| points < x }
end
scale = [0, 40, 50, 60, 70, 80, 101]
grade(39, scale)
# => 1
grade(40, scale)
# => 2
如果没有,那么使用这个:
def grade(points, scale)
scale.to_a.bsearch { |upto, _| points < upto }.last
end
scale = {40 => 1, 50 => 2, 60 => 3, 70 => 4, 80 => 5, 101 => 6}
grade(39, scale)
# => 1
grade(40, scale)
# => 2
我目前正在 Ruby 编写一个自动化的团队组建程序,它根据学生的技能组成不同的团队。该技能来自前一年学生的成绩(即 [0;100] 范围内的整数)。我已经实现了一个默认版本的成绩到技能转换方法,其中成绩根据以下阈值转换为技能
[0;39] => 1
[40;49] = > 2
[50;59] = > 3
[60;69] = > 4
[70;79] = > 5
[80;100] = > 6
这是通过 case/when 语句实现的 但是,该程序将根据教师的使用而设计,我想让教师能够对如何衡量学生的技能做出自己的解释(例如,他可能希望拥有更少或更多的技能组或给定技能组的不同阈值)。 我的想法是他将能够以哈希的形式将它们作为命名参数传递,将 2 值数组作为键(成绩阈值)和整数作为值(技能),但是我正在努力思考一个巧妙的方法来实现它。 是否有可能实现可变数量的 when 语句,其中每个语句负责给定的技能(比如将它们放在某种循环中?)。或者你能想到任何其他方法可以解决这个问题吗? 非常感谢您的帮助!
给定这样的结构:
values = {
0..39 => 1,
40..49 => 2,
50..59 => 3,
60..69 => 4,
70..79 => 5,
80..100 => 6
}
您可以使用 find
来获取符合特定条件的第一个条目:(假设范围不重叠并且没有 "holes" – 您可能想要验证提供的数据第一)
grade = 52
range, skill = values.find { |r, v| r.cover?(grade) }
range #=> 50..59
skill #=> 3
使用 bsearch
比 find
性能更高,只要你能保证数组有序 – O(log n)
vs find
的 O(n)
–没有任何额外的内存支出(堆栈框架除外,呵呵)。此外,由于您的范围(大概)是连续的,它们之间没有任何空洞,您可以只指定阈值。
因此,如果您的索引始终为“1..N”,则此方法可行:
def grade(points, scale)
scale.bsearch_index { |x| points < x }
end
scale = [0, 40, 50, 60, 70, 80, 101]
grade(39, scale)
# => 1
grade(40, scale)
# => 2
如果没有,那么使用这个:
def grade(points, scale)
scale.to_a.bsearch { |upto, _| points < upto }.last
end
scale = {40 => 1, 50 => 2, 60 => 3, 70 => 4, 80 => 5, 101 => 6}
grade(39, scale)
# => 1
grade(40, scale)
# => 2