【问题标题】:Ruby math: take a number from a larger number range and calculate where it falls on a smaller rangeRuby 数学:从较大的数字范围中取一个数字并计算它在较小范围内的位置
【发布时间】:2012-10-31 11:43:57
【问题描述】:

假设我有一个 key => 数字值的排序哈希,如下所示:

h = { "sebastian" => 0.04, "joshua" => 0.1, "alli" => 0.2, "oliver" = >0.2,  
    ... 
    "wendi" => 1.9, "esther" => 2.1, "mauricio" => 2.6, "fred" => 3.9 }

在此哈希中,最小值为 0.04,最大值为 3.9。 (在其他哈希中,这可能完全不同,例如 3..90、1.5..900 等)

现在我有一个有序数组,如下所示:

a = ["lowest", "lower", "low", "normal", "high", "higher", "highest"]

给定哈希中的任何一个值,比如 1.9,我如何确定该值落在数组中描述的范围内的哪个位置?

(请原谅这里的 Ruby 和数学新手!)

谢谢!

更新 1:

对不清楚的问题表示歉意。仍在试图弄清楚如何描述这一点。

这是一个概念性示例,说明我目前如何解决我的问题,可能会有所帮助。

scores = { "sebastian" => 0.04, "joshua" => 0.1, "alli" => 0.2, "oliver" => 0.2, 
           "wendi" => 1.9, "esther" => 2.1, "mauricio" => 2.6, "fred" => 3.9 }
adjectives = ["lowest", "lower", "low", "average", "high", "higher", "higher"]

scores.each_pair do |student, score|
    adj_idx = case score
        when 3.35..4 then 6
        when 2.8..3.34 then 5
        when 2.25..2.7 then 4
        when 1.7..2.24 then 3
        when 1.15..1.6 then 2
        when 0.6..1.16 then 1
        else 0
    end
    puts "#{student} score was in the #{adjectives[adj_idx]}."
end

所以我的问题是: 给定一系列可能不同的学生分数(例如,分数可能是 GPA 0.0..4.0,或考试分数 0..110),以及一系列“形容词” ” 也可能会有所不同(例如,“更高”和“更低”可能会被删除),有没有一种方法可以将分数映射到形容词,而无需像我上面所做的那样“手动”构建每个案例。

再次感谢!

更新 2:

感谢您的所有帮助。我想我已经得到了以下解决方案。关键公式是这样的:

adj_idx = ( (adjectives.size - 1) * ( (score - min_score).to_f / (max_score - min_score).to_f ) ).round

min_score = scores.values.min
max_score = scores.values.max

scores.each_pair do |student, score|
    adj_idx = ( (adjectives.size - 1) * ((score - min_score).to_f / (max_score - min_score).to_f)  ).round
    puts "#{student} score was in the #{adjectives[adj_idx]} range."
end

【问题讨论】:

  • 你能解释一下“它落在哪里”的意思吗?你的意思是如果它被插入到数组中,它的索引是什么?对不起,我没有关注....
  • 确定。好的,我的意思是,我如何计算 1.9 在 0.04 到 3.9 的数字范围内是否是“最低”、“较低”、“低”等。如果 1. 数字范围不同,例如 1.5..300 AND 2. 标签数组不同,例如 a = [-5, -4, -3, - 2、-1、0、1、2、3、4、5]。希望这是有道理的。
  • 您如何定义“最低”、“较低”、……“最高”是什么?甚至分道扬镳?如果它在两个之间,你会舍入还是占据地板或天花板?
  • @AndrewMarshall,我已经更新了我的问题。希望现在更清楚了。谢谢。
  • “有没有一种方法可以将分数映射到形容词,而无需像我上面所做的那样“手动”构建每个案例“是的,描述您用于手动构建阈值的算法,然后用代码实现它.请注意,没有一种正确的方法可以做到这一点 - 您是否希望将值范围以线性、几何或指数方式划分?

标签: ruby arrays math hash map


【解决方案1】:

如果您希望将值范围线性分成大小相等的子范围,这应该可以为您解决问题:

min = scores.values.min
max = scores.values.max
nsub = adjectives.size
tresholds = (1..nsub).map do |n|
  min + (max - min) * (n / nsub.to_f)
end

scores.each_pair do |student, score|
  adj_index = tresholds.index {|t| t >= score }
  puts "#{student} score was in the #{adjectives[adj_idx]}."
end

【讨论】:

  • 太棒了。谢谢。是的,线性是我一直在寻找的。我对红宝石很陌生,我必须研究你的解决方案才能完全理解。 fwiw,它给出的结果与我刚刚添加到上面的原始问题中的解决方案略有不同。给定 scores = { "sebastian" => 0.04, "joshua" => 0.25, "alli" => 0.68, "oliver" => 1.3, "wendi" => 1.9, "esther" => 2.1, "mauricio" => 2.8, "patrick" => 3.15, "fred" => 3.9 },我给毛里西奥“高”分,而你给他“更高”分。
【解决方案2】:

你可以定义一个带范围的数组:

a = [["lowest",(0.01..0.09), ["lower",(0.1..0.9)], ...]

然后遍历您的哈希并分配文字范围:

h.each do |key,value|
  literal_range = a.find { |(literal,range)| range.include?(value) }.first
  h[key] = literal_range if literal_range
end

结果会是这样的:

{ "sebastian" => 'lowest', "joshua" => 'lower', ... }

这个问题不是很清楚,所以我做了一些猜测,但我认为它会给你一些思考。

【讨论】:

  • 谢谢,我想我想弄清楚的是是否可以计算整个哈希(0.04..3.9)中的值如何映射到“形容词”数组而无需手动定义每个范围我自己。那有意义吗?我在原帖中添加了更多细节。
【解决方案3】:

你需要自己定义什么是lowestlower等等

rankings = {0.04         => 'lowest',
            (0.05..1.00) => 'lower',
            (1.01..1.50) => 'low',
            (1.51..2.50) => 'normal',
            (2.51..2.90) => 'high',
            (2.91..3.89) => 'higher',
            3.90         => 'highest',
           }

那么你可以这样做:

puts rankings.detect { |range, ranking| range === h['joshua'] }.last
#=> lower

【讨论】:

  • 谢谢,这类似于我目前解决问题的方式。我想知道是否有办法做到这一点而不必“手动”映射我的范围。我用一个(希望)更清晰的例子更新了我原来的问题。
  • 你必须以某种方式映射它,没有将范围映射到英语形容词的魔法函数......现在,也许有更聪明的方法来做到这一点,比如在 Range 类上定义一个方法,但是,您仍然必须在某处编写映射
  • 取分数值范围内的最小值和最大值与 adjectives.size 一起,假设 1) 形容词分布均匀, 2) adjectives.first 代表最低范围, adjectives.last 代表最高范围,我想那里可以写一个等式来平等地映射它们。例如,如果分数范围是 [0..100],形容词是 [D,C,B,A] 那么我们可以除以 100/4 并且“神奇地”将 0..25 映射到 D, 26.. 50 到 C,51..75 到 B,76..100 到 A。这有意义吗?
  • @seanomlor 如果你有算法,为什么不试着写代码呢?
  • 你是对的。对不起。我是 ruby​​ 的新手,也在数学上苦苦挣扎。我相信这是解决方案: ((adjectives.size - 1) * ((score - min_score).to_f / (max_score - min_score).to_f) ).round
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-22
相关资源
最近更新 更多