2012-08-14 45 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