我应该如何在ruby中对这些数据进行客观化?

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)

我认为我需要的是一个具有其他对象的可变长度存储的对象.那可能吗?关于我应该阅读什么的任何指示?

Cat*_*per 7

这是一个解析该文本行的对象:

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是不可变的(只读); 这可以防止其他对象更改数据.