2017-02-04 4 views
0

Iは、以下がそれの一つの列となっているデータ・ダンプ、有する(即ち、「{...}」)括弧の各ペア内文字列内の数値を比較してそのうちの1つを表示する方法は?

{,lat:26.3832456,distance:678.4075116373302,lon:120.4731951,address:tourism:viewpoint,},{,lat:26.3830149,distance:622.2862561842148,lon:120.473753,address:name:xe7,xbe,x85,xe6,xbc,xa2,xe5,x9d,xaa,tourism:viewpoint,},{,lat:26.3833609,distance:363.7364243757184,lon:120.4763708,address:name:xe5,x9c,x8b,xe4,xb9,x8b,xe5,x8c,x97,xe7,x96,x86,tourism:viewpoint,},{,lat:26.3823648,distance:223.60523114628876,lon:120.4821298,address:name:xe5,x90,x8e,xe6,xbe,xb3,natural:bay,},{,lat:26.3788243,distance:470.02293394005875,lon:120.480733,address:name:xe5,x90,x8e,xe6,xbe,xb3,xe5,xb1,xb1,source:GNS,natural:peak,},{,lat:26.3750042,distance:893.4290785528082,lon:120.4808826,address:name:xe8,x93,xae,xe8,x8a,xb1,xe5,x9c,x92,source:GNS,natural:peak,},{,lat:26.3763331,distance:742.92090763674,lon:120.4795115,address:name:xe8,xa5,xbf,xe5,xbc,x95,xe5,xb3,xb6,place:hamlet,source:GNS,},{,lat:26.378645,distance:623.327734488774,lon:120.4839399,address:source:PGS,natural:coastline,},{,lat:26.3801244,distance:418.6308872217763,lon:120.4772875,address:highway:residential,},{,lat:26.3791422,distance:434.6736862343828,lon:120.4792953,address:highway:residential,},{,lat:26.3779802,distance:739.2129423740619,lon:120.4751349,address:highway:unclassified,},{,lat:26.3770924,distance:675.0424314750977,lon:120.4815607,address:highway:residential,},{,lat:26.3760869,distance:798.0261247167285,lon:120.4821517,address:highway:path,},{,lat:26.3766434,distance:737.1372670528466,lon:120.4821003,address:highway:path,},{,lat:26.3813278,distance:384.84440601318613,lon:120.4766175,address:highway:path,},{,lat:26.3755092,distance:833.3985359252805,lon:120.4802778,address:highway:road,},{,lat:26.3785345,distance:496.6253230490143,lon:120.4799081,address:highway:road,} 

部分は1つのIDに関する情報を表します。中括弧の各ペアのdistanceフィールドを比較して、最小距離の中括弧の内容を表示する必要があります。このよう

{,lat:26.3823648,distance:223.60523114628876,lon:120.4821298,address:name:xe5,x90,x8e,xe6,xbe,xb3,natural:bay,} 

distanceフィールドの最小値を有するものである:例えば、上の行の例では、私は次の出力したいです。

これを行う方法?私はすべての距離は、それらを比較するために抽出するために、次のコードを書かれているが、それでも、それは動作しません:

require 'rubygems' 
require 'mechanize' 
require 'csv'  
CSV.open('Output.csv', "wb") do |csv| 
    CSV.foreach('Original.csv', :headers=>true) do |row| 
     vector = row.split(",")  
     dist = vector.match("^.*\/distance:\/(.*)\/")  
     csv << dist 
    end 
end 

私の考えは、最小のを見つけ、それらを比較し、すべての距離を抽出するために戻っていましたその特定の距離のカッコを特定し、その中カッコでコンテンツを出力することができます。しかし、これはこれを行う一種の複雑な方法のように思えます。最小の距離のブレースを出力するよりエレガントな方法はありますか?ありがとう。

答えて

2

非常にエレガントではないが、動作するようです:sはあなたの最初のデータになります

s.scan(/\{[^{}]*\}/).min_by { |r| r =~ /distance:(.*),/; $1.to_f }

文字列としてダンプします。

scanは、最初のデータをレコードの配列に分割します(中括弧のペアの間は、中括弧ではないものがレコードの一部とみなされます)。 min_byは、その配列をループして、パラメータとして渡されたブロックによって与えられる最小値を持つレコードを探します。この場合、ブロックはレコード内の距離値を探すだけの正規表現です。

+0

ワウ。あなたのコードは、最大距離を持つコードを与えます(私の要求に合わせて "max_by"を "min_by"に変更しました)。しかし、それはどのように機能するのですか、私は理解できないものです!これがどういう仕組みになっているのかちょっと説明してください。 – Kristada673

1

strを与えられた文字列を保持する変数とする。

最初のステップは、右ブレースが先行し、左括弧が続くカンマで文字列を分割することである。

r0 =/
    (?<=}) # match a right brace in a positive lookbehind 
    ,  # match a comma 
    (?={) # match a right brace in a positive lookahead 
    /x  # free-spacing regex definition mode 

arr = str.split(r0) 
    #=> ["{,lat:26.3832456,distance:678.4075116373302,lon:120.4731951,...}", 
    # "{,lat:26.3830149,distance:622.2862561842148,lon:120.473753,...}", 
    # ... 
    # "{,lat:26.3750042,distance:893.4290785528082,lon:120.4808826,...}", 
    # ... 
    # "{,lat:26.3785345,distance:496.6253230490143,lon:120.4799081,}"] 

str.split(r0).size 
    #=> 17 

我々は次にmax_byのブロックを返す配列にmax_byを適用floatで表される各文字列の距離。

r1 =/
    (?<=,distance:) # match ",distance:" in a positive lookbehind 
    \d+    # match one or more digits 
    \.    # match a decimal point 
    \d+    # match one or more digits 
    /x  # free-spacing regex definition mode 

arr.max_by { |s| s[r1].to_f } 
    #=> "{,lat:26.3750042,distance:893.4290785528082,lon:120.4808826,...}" 

私は、配列のすべての文字列に距離フィールドが含まれていると仮定しました。いくつかの文字列は、上記の式はに変換されますない場合があります。

arr.max_by { |s| (s[r1] || -Float::INFINITY).to_f } 

1つはまた、文字列は、距離フィールドが含まれて返されたかどうかを確認する必要があります。

これを1つの表現にまとめることができます。

str.split(/(?<=}),(?={)/). 
    max_by { |s| (s[/(?<=,distance:)\d+\.\d+/] || -Float::INFINITY).to_f } 
関連する問題