红宝石可以有一个以浮点数开头的范围吗?



我是红宝石的初学者,试图用它来帮助我分析生物数据。我需要尝试将一组数据(数组中的数字)与具有一定特异性(例如 number+/- 0.25)的另一组数据相匹配 我想出了这个(到目前为止)将一个数据集更改为范围,而不是数字:

def range(arr)
c = []
arr.each do |b|
b = (b-0.25..b+0.25)
b = b.to_a
c << b
end
c = c.flatten
return c
end

代码给出了所需的数组,但是我总是得到

TypeError: can't iterate from Float.

我该如何解决这个问题?

背景

这是我的实际数据示例:

119.0456 119.0714 119.0721 119.0737 120.0772 130.0746 131.0737 136.0721 140.0951 143.0697 154.038 154.0744 154.1108 155.0949 156.054 169.053 170.1422 171.0646

171.0686 174.0644 174.0795 180.0539 182.1059

我需要将其与理论集匹配,我需要在公差为 0.002 的情况下生成我正在逐步处理代码以生成我的理论集,因为我仍然不熟悉编码,只是想知道如何围绕我的理论集创建一个 +/- 0.002 的范围以将其与实际集相匹配。

红宝石的范围可以从浮点数开始吗?

是的,您可以使用浮点数创建范围:

r = 0.25..0.75
#=> 0.25..0.75

但是你不能使用Range#each来遍历它,因为each依赖于succ(例如Integer#succ),Float不实现该方法。

相反,您可以将Range#step与 take 一个显式增量值一起使用:

r.step(0.1) { |f| puts f }

输出:

0.25
0.35
0.45
0.55
0.65
0.75

只是为了好玩,让我们看看如果我们使用Float#next_float会发生什么:

class Float
alias succ next_float
end
r = 0.25..0.75
r.each { |f| puts f }

输出:

0.25
0.25000000000000006
0.2500000000000001
0.25000000000000017
0.2500000000000002
0.2500000000000003
0.25000000000000033
0.2500000000000004
0.25000000000000044
0.2500000000000005
0.25000000000000056
0.2500000000000006
...

代码给出了所需的数组,但是我总是得到

TypeError: can't iterate from Float.

我该如何解决这个问题

您可以改为构建一个范围数组:

def range(arr)
arr.map { |b| b-0.25..b+0.25 }
end
range [1, 2, 3]
#=> [0.75..1.25, 1.75..2.25, 2.75..3.25]

首先,这段代码:

def range(arr)
c = []
arr.each do |b|
b = (b-0.25..b+0.25)
c << b
end
return c
end

基本上采用一个数组并创建一个新数组,每个项目都根据规则进行修改。在 Ruby 中,您可以使用.map()来实现该目的:

def range(arr)
arr.map { |b| (b-0.25..b+0.25) }
end
其次,正如其他人所说,浮点数

范围确实存在,但你不能迭代浮点数的范围,因为 Ruby 无法知道你想要什么增量。范围 (1.0 .. 2.0) 在技术上包含无限数量的数字(例如 1.2324123 和 1.9232311),因此如果不说明每个步骤应该有多大,就无法迭代。您可以像这样执行此操作:

range.step(0.1) { |f| #do stuff with f }

但是,如果您的目标是比较数组,看看 [1,2,3] 是否适合范围 [0.75..1.25, 1.75..2.25, 2.75..3.25],则根本不需要迭代范围。您应该改用.cover?()方法,以查看数字是否在某个范围内:

def in_range(arr, ranges)
return false unless arr.size == ranges.size
arr.zip(ranges).do { |a, r| return false unless r.cover? a }
return true
end

如果我正确理解了您的问题,您可以改为这样做:

arr1 = [1,2,3]
arr2 = [1.25, 1.85, 4.25]
s = 0.25
arr1.zip(arr2).select { |a, b| (a-b).abs <= s }
#=> [[1, 1.25], [2, 1.85]]

关键方法Array#zipArray#selectFloat#abs

您不显示范围方法的结束end- 显示的end关闭arr.each循环。

这可能是问题所在吗?

最新更新