前の行と同じであれば空欄になっているCSVテキストのセルを全部埋めたい
国、州/県、都市を定義した、こんなCSVテキストがあったとします。
日本,東京,新宿
,,渋谷
,兵庫,神戸
アメリカ,カリフォルニア,サンフランシスコ
,,ロサンゼルス
データは予めソートされていて、国や州が前のデータと同じであれば空欄になっています。
このテキストを変換して、セルを全部埋めるプログラムを作りたいと思っています。
すなわち、期待するのは以下のようなアウトプットです。
日本,東京,新宿
日本,東京,渋谷
日本,兵庫,神戸
アメリカ,カリフォルニア,サンフランシスコ
アメリカ,カリフォルニア,ロサンゼルス
とりあえず僕の方で愚直にこんなロジックを考えたんですが、ブロックの外で定義するcurrent_country
、current_state
や、if country.size > 0 ... end
がDRYになってない感じが自分でもちょっとしっくりきません。
def fill_blank(csv_text)
current_country, current_state = nil, nil
csv_text.lines.map { |line|
country, state, city = line.chomp.split(',')
if country.size > 0
current_country = country
end
if state.size > 0
current_state = state
end
[current_country, current_state, city].join(',')
}.join("\n")
end
もうちょっと短くてわかりやすい、スマートなロジックは作れないでしょうか?
Railsで動かすのでActiveSupportのメソッドを使うのもOKです。
参考までにテストコード付きのサンプルコードを載せておきます。
require 'test/unit'
class FillBlankTest < Test::Unit::TestCase
def fill_blank(csv_text)
current_country, current_state = nil, nil
csv_text.lines.map { |line|
country, state, city = line.chomp.split(',')
if country.size > 0
current_country = country
end
if state.size > 0
current_state = state
end
[current_country, current_state, city].join(',')
}.join("\n")
end
def test_fill_blank
input = <<-TEXT
日本,東京,新宿
,,渋谷
,兵庫,神戸
アメリカ,カリフォルニア,サンフランシスコ
,,ロサンゼルス
TEXT
output = <<-TEXT.chomp
日本,東京,新宿
日本,東京,渋谷
日本,兵庫,神戸
アメリカ,カリフォルニア,サンフランシスコ
アメリカ,カリフォルニア,ロサンゼルス
TEXT
assert_equal output, fill_blank(input)
end
end
みなさんのアイデアをお待ちしています。