2016-04-05 17 views
0

私はセパレータとしてttを使用するcsvファイルを持っています。しかし、一部の値がtで終わることがあるため、いくつかのエッジケースが壊れています。私はこのGem https://github.com/tilo/smarter_csvを使ってcsvデータを取得しています。壊れたデータのひどく設計されたcsvファイルが値を破る

例:

4909ttZSWttPrince RupertttCanadattCAttNorth Americatt54.3333tt-130.283 

出力:(市と国の値に注意してください)

{:id=>4909, :code=>"ZSW", :city=>"Prince Ruper", :country=>"tCanada", :country_code=>"CA", :continent=>"North America", :coordinate_x=>54.3333, :coordinate_y=>-130.283} 

単語がトンで終わる場合かどうかを確認することをCSVリーダーを伝える方法があります次の文字は大文字で始まり、それ以外の場合は区切りません。 ((tt)t repeatに注意してください)。これは私の現在のコードです:

options = { 
    :col_sep => 'tt', 
    :headers_in_file => false, 
    :user_provided_headers => [ 
    "id", 
    "code", 
    "city", 
    "country", 
    "country_code", 
    "continent", 
    "coordinate_x", 
    "coordinate_y" 
    ] 
} 
records = SmarterCSV.process(filename, options) 
+6

Wow、セパレータとして「tt」。これは本当に悪い選択です。 'tt'を含む言葉がたくさんあります。このようなひどく設計されたフォーマットをサポートするための回避策やハックは、私にとって時間の無駄だと感じています。最初にフォーマットを修正するオプションはありますか? – spickermann

+0

@spickermann私は全く同意します。私は真剣にセパレーターとして 'tt'を使うことは誰がやろうとしていたのでしょうか?そこでは論理はありますが、私はそれに対処しなければならないと思います。これが私が「ひどく設計された...」と題された理由です。 – Kunok

答えて

1

@mudasobwaからインスパイアされました。答えコードをあまり変更しなくても済む別のソリューションも見つかりました。私は:col_sepの値をttから@mudasobwaによって提供される正規表現に置き換えました。

options = { 
    :col_sep => /tt(?=[^t]|tt)/, 
    :headers_in_file => false, 
    :user_provided_headers => [ 
    "id", 
    "code", 
    "city", 
    "country", 
    "country_code", 
    "continent", 
    "coordinate_x", 
    "coordinate_y" 
    ] 
} 
records = SmarterCSV.process(filename, options) 

版のノート:私はnilの値を許可する

​​3210

で正規表現

/tt(?=[^t])/ 

を交換しています。

+1

ああ、クールな、このスマートな宝石は本当にスマートです:)私はそれが区切り記号として正規表現を理解するとは思っていませんでした。 – mudasobwa

+1

これは本当にクールですが、 'nil'カラムには問題があります。 'tttt'を取得しようとすると、' t'の最後のカップルだけがセパレータとして認識されます(私はあなたの応答を編集しました)。 –

+0

'valuettvaluettttvalue'のようなケースですか? – Kunok

3

スマートな宝石はここではあまりにも愚かなようです。

私は行くだろう:これは、配列の配列を生成します

File.readlines('path/to/file').map do |line| 
    line.split(/tt(?=[^t])/) 
end 

。この「スマートな」宝石によって提供される出力を望むかどうか:

File.readlines('path/to/file').map do |line| 
    user_provided_headers.zip(line.split(/tt(?=[^t])/)).to_h 
end 

Voilà。上記の動作は、セルの値が小文字の "t"で始めることができないことを前提としています。

Sidenote:「誰かが書いたコードをどのように使うのか」が素早くなり、小さなコードを書くのは簡単ではありません。

0

セパレータ文字列を;のような別の文字列に置き換えないのはなぜですか? はたぶん余分な作業のように聞こえるが、それはあなたに多くの時間を節約し、ちょうどこのような何かを実行して構成されています

"HolattCatttHey".gsub(/(tt[A-Z])/) { |m| ";#{($1).sub('tt','')}"} 
=> "Hola;Cat;Hey" 

が、この後は、あなたが喜んであなたの宝石を使用することができます。

+0

私は本当にそれをしたいと思っています。私は自分のためにこのタスクを行うスクリプトを用意していますが、残念ながら私はcsvファイルを変更することはできません。 – Kunok

関連する問題