2012-08-14 61 views
0

我正在做數據處理,一項任務是獲取人員分佈的統計信息。對名字叫「約翰·多伊」的人來說,有不同的州,ca,ar和ny,以及不同年齡組,二十歲,三十歲等。{1,2}或{3}是人民的身份。ruby​​更改字符串的內容

"john doe" => "ca:tw#2{1,2}:th#1{3};ar:tw#1{4}:fi#1{5};ny:tw#1{6};" 

現在,如果我想要得到與年齡tw約翰doe的id,我應該如何得到它們?也許使用正則表達式?如果我想添加一個新的ID,比如說100,現在它變成

"john doe" => "ca:tw#3{1,2,100}:th#1{3};ar:tw#1{4}:fi#1{5};ny:tw#1{6};" 

我應該怎麼做? 謝謝!

+4

你爲什麼要使用一個字符串,而不是存儲更適合數據結構的這個數據? – 2012-08-14 20:47:59

+0

根據您在做什麼,它可能有助於導入數據並將其轉換爲XML文檔。像Nokogiri這樣的寶石可以很快地與它一起工作。 – 2012-08-15 14:21:01

回答

1

如果你想堅持字符串操作,你可以使用正則表達式和gsub。

這是一種方法。它可以使用一些清理(例如錯誤處理,重新分解等),但我認爲它會讓你開始。

def count(details, location, age_group) 
    location_details = /#{location}(.+?);/.match(details)[1] 
    age_count = /#{age_group}#(\d+)\{/.match(details)[1] 
    return age_count.to_i 
end 

def ids(details, location, age_group) 
    location_details = /#{location}(.+?);/.match(details)[1] 
    age_ids = /#{age_group}#\d+\{(.+?)\}/.match(details)[1] 
    return age_ids 
end 

def add(details, location, age_group, new_id) 
    location_details = /#{location}(.+?);/.match(details)[1] 
    new_count = count(details, location, age_group) + 1 
    new_ids = ids(details, location, age_group) + ',' + new_id 
    location_details.gsub!(/#{age_group}#\d+\{(.+?)\}/, "#{age_group}##{new_count}{#{new_ids}}") 
    details.gsub!(/#{location}(.+?);/, "#{location}#{location_details};") 
end 

你可以看到它產生你想要的結果(至少在功能上,不知道性能):

names = {"john doe" => "ca:tw#2{1,2}:th#1{3};ar:tw#1{4}:fi#1{5};ny:tw#1{6};"} 
puts count(names["john doe"], 'ca', 'tw') 
#=> 2 
puts ids(names["john doe"], 'ca', 'tw') 
#=> 1,2 
names["john doe"] = add(names["john doe"], 'ca', 'tw', '100') 
puts names["john doe"] 
#=> ca:tw#3{1,2,100}:th#1{3};ar:tw#1{4}:fi#1{5};ny:tw#1{6}; 
1

在程序內部使用字符串沒有意義。您可以在存儲字符串時讀取數據,或者以這種方式寫回數據,但應該以易於操作的方式存儲數據。例如:

data = { 
    "john doe" => { 
    "ca" => { 
     "tw" => [1,2], 
     "th" => [3] 
    }, 
    "ar" => { 
     "tw" => [4], 
     "fi" => [5] 
    }, 
    "ny" => { 
     "tw" => [6] 
    } 
    } 
} 

鑑於此,加州李四在20年代的ID是data['john doe']['ca']['tw']。這種John Doe的數量是data['john doe']['ca']['tw'].length;第一個ID是data['john doe']['ca']['tw'][0],第二個是data['john doe']['ca']['tw'][1]。您可以使用data['john doe']['ca']['tw'] << 100添加ID爲100的ID; 100將會是data['john doe']['ca']['tw'][2]的值。

但是,如果我寫這個,我可能會用年齡範圍鍵(20,30,50)的實際數字來代替那些模糊的字母前綴。

+0

感謝馬克,這是有道理的,但散列處理大型數據集時似乎很慢。我試過你的方法,它需要很長時間,所以我正在考慮字符串表示。 – 2012-08-14 21:00:56

+0

不確定字符串操作將比哈希訪問快多少。你使用的是什麼Ruby實現? – 2012-08-14 23:28:37

+0

像這樣name_hash = {:「jose garcia」=> {:ca => {:tw => {:count => 2,:id =>「1,2,」},:th => {:count => 3,:id =>「3,4,5,」}},:ak => {:tw => {:count => 1,:id =>「22,」}}}, : john doe「=> {:ar => {:tw => {:count => 1,:id =>」95,「}}}} – 2012-08-14 23:31:42