2014-03-12 106 views
2

我想用一个Ruby脚本替换遗留系统中的组件。该系统的一部分接受一个包含ASCII'0'和'1'的字符串,显然表示位置的位域。然后它将这些位置转换为一串逗号分隔的两个代码(大部分是美国州)。红宝石多个阵列比较

我有一个Ruby方法可以做到这一点,但它似乎并没有像Ruby那样做的最好方式。 Ruby有一吨的内置的遍历方式和操作阵列,我觉得我不使用它们发挥到极致:

# input "0100010010" should return "AZ,PR,WY" 
def locations(bits)   
    # Shortened from hundreds for this post. :u? is for locations I have't figured out yet. 
    fields = [ :u?, :az, :de, :mi, :ne, :wy, :u?, :u?, :pr, :u? ] 
    matches = [] 
    counter = 0 
    fields.each { |f| 
    case bits[counter] 
     when '1' then matches << f 
     when '0' then nil 
     else raise "Unknown value in location bit field" 
    end 
    counter += 1 
    } 
    if matches.include(:u?) then raise "Unknown field bit set" end 
    matches.sort.join(",").upcase 
end 

这将是一个更好的方式来做到这一点?

似乎与“Ruby方式”有相反的变量浮动。我试图寻找使用Array#map的方法,并且我发现没有什么明显的。我也试着用Google搜索关于数组的Ruby成语。

回答

5
matches = fields.select.with_index { |_,i| bits[i] == '1' } 
# => [:az, :wy, :pr] 

要验证bits仅持有0 S和1 S,你仍然可以做

raise "Unknown value in location bit field" if !bits.match(/^[01]*$/) 
+0

编辑此评论 - 我的错误。很好的答案! – joews

+0

优秀的方法。 –

1

您可以结合each_with_indexmapcompact

fields.each_with_index.map do |v,i| 
    v if bits[i] == '1' 
end.compact 

each_with_index返回每个每个值及其整数索引的迭代。

map使用传递块的返回值为每个输入值生成输出值。如果其相应的位被设置,该块返回值,如果不是,则隐含地返回nil

compact返回删除了所有nil值的输出数组的副本。

欲了解更多详情,请参阅文档EnumerableArray

+0

也可以做'map.with_index'。 –

+0

重读http://www.ruby-doc.org/core-2.1.1/Array.html#method-i-map页面后,我看到了each_with_index,我认为这将是最好的答案 – Sqeaky

2

使用Array#zipArray#reduce

bits.split('').zip(fields).reduce([]) do |a, (k, v)| 
    k == '1' ? a << v.to_s.upcase : a 
end.sort.join(',') 
# => "AZ,PR,WY 

说明:

1)split位转换成字符数组:

bits.split('') # => ["0", "1", "0", "0", "0", "1", "0", "0", "1", "0"] 

2)zip两个阵列以产生对数组(通过位置)

bits.split('').zip(fields) # => [["0", :u?], ["1", :az], ["0", :de], ["0", :mi], 
# ["0", :ne], ["1", :wy], ["0", :u?], ["0", :u?], ["1", :pr], ["0", :u?]] 

3)reduce阵列服用所需元素根据条件

.reduce([]) do |a, (k, v)| 
    k == '1' ? a << v.to_s.upcase : a 
end # => "[AZ,WY,PR] 

4)sort the r他们的元素得到期望的字符串

.sort.join(',') # => "AZ,PR,WY" 
+1

如果您可以在此示例中添加一点解释,这将有所帮助。 – Fenton

+0

@SteveFenton:我已经添加了一些解释,谢谢。 –

+0

@SteveFenton:顺便提一下。我真的同意我们应该面对这样一个采访:http://www.stevefenton.co.uk/Content/Blog/Date/201403/Blog/If-You-Show-Me-Yours/ –