And*_*dyM -1 ruby oop ruby-on-rails object-oriented-analysis
我有以下文本放入一些Ruby对象,以便我可以将它们写入数据库以在rails应用程序中使用.这些数据是波浪预报模型的一些输出,它显示了海洋中特定点的海洋膨胀.第一列是日和小时,然后组合膨胀(对此不感兴趣),接着是单个膨胀,其可以在任何一小时内从1到6膨胀变化.
+-------+-----------+-----------------+-----------------+-----------------+
| day & | Hst n x | Hs Tp dir | Hs Tp dir | Hs Tp dir |
| hour | (m) - - | (m) (s) (d) | (m) (s) (d) | (m) (s) (d) |
+-------+-----------+-----------------+-----------------+-----------------+
| 15 3 | 0.94 3 | 0.74 4.4 69 | 0.43 10.6 186 | 0.39 4.8 351 |
| 15 4 | 0.90 3 | 0.71 4.2 68 | 0.43 10.7 186 | 0.34 4.7 347 |
| 15 5 | 0.85 3 | 0.65 4.1 72 | 0.42 10.7 186 | 0.35 4.4 351 |
| 15 6 | 0.81 3 | 0.61 4.2 72 | 0.42 10.7 186 | 0.32 4.5 350 |
| 15 7 | 0.77 2 | | 0.41 10.8 186 | |
| 15 8 | 0.73 2 | | 0.40 10.8 186 | |
| 15 9 | 0.70 3 | 0.51 3.8 74 | 0.40 10.7 187 | 0.26 4.1 350 |
| 15 10 | 0.67 3 | 0.49 3.8 73 | 0.39 10.7 187 | 0.24 4.2 349 |
| 15 11 | 0.65 3 | 0.47 3.7 73 | 0.38 10.7 186 | 0.23 4.1 352 |
| 15 12 | 0.63 2 | | 0.37 10.7 187 | |
| 15 13 | 0.63 2 | | 0.35 10.6 187 | |
Run Code Online (Sandbox Code Playgroud)
我对日期,膨胀次数以及每次膨胀的信息感兴趣.我所追求的是一个包含日/小时作为键的对象,还包含每个膨胀的单个数据.每个小时的膨胀次数会有所不同.如果我加载行:
| 15 11 | 0.65 3 | 0.47 3.7 73 | 0.38 10.7 186 | 0.23 4.1 352 |
Run Code Online (Sandbox Code Playgroud)
我希望通过以下调用从对象中获取信息:
@forecast.date #=> 15:11
@forecast.numswells #=> 3 for the total swells present on that date
@forecast.swell.1.height #=> 0.47
@forecast.swell.1.direction #=> 73
@forecast.swell.3 #=> a swell object with all info in it for swell 3
Run Code Online (Sandbox Code Playgroud)
我认为我需要的是一个具有其他对象的可变长度存储的对象.那可能吗?关于我应该阅读什么的任何指示?
这是一个解析该文本行的对象:
class DayOnTheWater
Swell = Struct.new(:hs, :tp, :d)
attr_reader :day, :hour
def initialize data_line
data = data_line.split(/[|\s]/).delete_if {|col| col.empty?}
@day = data.shift
@hour = data.shift
2.times { data.shift } # remove combined swell data
@swells = data.each_slice(3).map { |hs, tp, d| Swell.new(hs.to_f, tp.to_f, d.to_i) }
end
def swells
@swells.to_enum
end
end
example = '| 15 11 | 0.65 3 | 0.47 3.7 73 | 0.38 10.7 186 | 0.23 4.1 352 |'
object = DayOnTheWater.new(example)
puts "day: #{object.day}"
puts "hour: #{object.hour}"
puts "\nSWELL DATA"
object.swells.each { |swell| puts swell.inspect }
puts "\nExample statistic:"
puts "Max Hs: #{object.swells.max { |a,b| a.hs <=> b.hs }}"
Run Code Online (Sandbox Code Playgroud)
输出:
day: 15
hour: 11
SWELL DATA
#<struct DayOnTheWater::Swell hs=0.47, tp=3.7, d=73>
#<struct DayOnTheWater::Swell hs=0.38, tp=10.7, d=186>
#<struct DayOnTheWater::Swell hs=0.23, tp=4.1, d=352>
Example statistic:
Max Hs: #<struct DayOnTheWater::Swell hs=0.47, tp=3.7, d=73>
Run Code Online (Sandbox Code Playgroud)
结构适用于简单的值对象.它们有缺点,但它们很快就可以输入.对于公开事物列表的对象,我总是返回一个Enumerable,而不是底层的数据对象(这里是swells方法).这很重要因为Enumerables是不可变的(只读); 这可以防止其他对象更改数据.