-1

Rails アプリで使用する DB に書き込むことができるように、次のテキストをいくつかの Ruby オブジェクトに入れます。データは、海の特定のポイントでの海のうねりを示す波予測モデルからの出力です。最初の列は曜日と時間、次に結合されたうねり (これには関心がありません)、その後に 1 時間に 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 |                 |

日付、うねりの数、各うねりに関する情報に興味があります。私が求めているのは、日/時をキーとして含み、各うねりの個々のデータも含むオブジェクトです。うねりの数は時間ごとに異なります。行をロードした場合:

| 15 11 | 0.65  3   |   0.47  3.7  73 |   0.38 10.7 186 |   0.23  4.1 352 |

次のような呼び出しでオブジェクトから情報を取得したいと思います。

@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

私が必要としているのは、他のオブジェクトの可変長ストアを持つオブジェクトだと思います。それは可能ですか?私が何を読むべきかについての指針はありますか?

4

2 に答える 2

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 }}"

出力:

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>

構造体は単純な値オブジェクトに適しています。それらには欠点がありますが、すばやく入力できます。もののリストを公開するオブジェクトの場合、私は常に Enumerable を返し、基になるデータ オブジェクト (ここでは swells メソッド) は返しません。Enumerable は不変 (読み取り専用) であるため、これは重要です。これにより、他のオブジェクトがデータを変更するのを防ぎます。

于 2012-11-16T20:45:58.187 に答える
1

いくつかの提案:

  • 一連のものswellsよりも複数形で使用することをお勧めします。swell
  • 長さが変化するものには、Array が最適です。配列の特定の要素を参照するときは、 、 など[]のメソッドの代わりに メソッドを使用する必要があります(おそらく、そもそもそれは不可能です)。その場合、ではなくから開始する必要があることに注意してください。1201
  • lengthうねりにメソッドを適用すると、簡単にうねりの数を取得できます。numswells特に頻繁に使用される場合を除き、そのための特定の方法を用意する必要はありません。

私はこのようなことをします:

data =
"| 15 11 | 0.65  3   |   0.47  3.7  73 |   0.38 10.7 186 |   0.23  4.1 352 |"

class Forecast
  attr_reader :date, :swells
  def initialize string
    _, date, _, swells = string.split("|", 4)
    @date = date.scan(/\d+/).join(":")
    @swells = swells.scan(/[^\|]+/).select{|s| s =~ /\S/}.map{|s| Swell.new(s)}
  end
end

class Swell
  attr_reader :height, :tp, :direction
  def initialize string
    @height, @tp, @direction = string.split(/\s+/).drop(1).map(&:to_f)
  end
end

@forecast = Forecast.new(data)
p @forecast.date
p @forecast.swells.length
p @forecast.swells[0].height
p @forecast.swells[0].direction
p @forecast.swells[2]

#=> "15:11"
#=> 3
#=> 0.47
#=> 73.0
#=> #<Swell:0x000000016401d0 @height=0.23, @tp=4.1, @direction=352.0>
于 2012-11-17T04:41:42.060 に答える