在ruby中将哈希与字符串的键/值合并

Merge a hash with the key/values of a string in ruby

我正在尝试将哈希与ruby中字符串的键/值合并。

1
2
3
h = {:day => 4, :month => 8, :year => 2010}
s ="/my/crazy/url/:day/:month/:year"
puts s.interpolate(h)

我发现的全部是迭代键并替换值。但是我不确定是否有更好的方法? :)

1
2
3
4
5
class String
 ?def interpolate(e)
 ? ?self if e.each{|k, v| self.gsub!(":#{k}","#{v}")}
 ?end
end

谢谢


无需重新发明Ruby内置组件:

1
2
3
h = {:day => 4, :month => 8, :year => 2010}
s ="/my/crazy/url/%{day}/%{month}/%{year}"
puts s % h

(请注意,这需要Ruby 1.9)


"更好"可能是主观的,但是这里的方法仅使用一次对gsub的调用:

1
2
3
4
5
class String
  def interpolate!(h)
    self.gsub!(/:(\\w+)/) { h[$1.to_sym] }
  end
end

因此:

1
2
>>"/my/crazy/url/:day/:month/:year".interpolate!(h)
=>"/my/crazy/url/4/8/2010"


其他想法可能是扩展String#%方法,以便它知道如何处理Hash参数,同时保留现有功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class String
  alias_method :orig_percent, :%
  def %(e)
    if e.is_a?(Hash)
      # based on Michael's answer
      self.gsub(/:(\\w+)/) {e[$1.to_sym]}
    else
      self.orig_percent e
    end
  end
end

s ="/my/%s/%d/:day/:month/:year"
puts s % {:day => 4, :month => 8, :year => 2010}
#=> /my/%s/%d/4/8/2010
puts s % ['test', 5]
#=> /my/test/5/:day/:month/:year


这对我来说似乎并不坏,但是另一种方法是使用ERB:

1
2
3
4
5
require 'erb'

h = {:day => 4, :month => 8, :year => 2010}
template = ERB.new"/my/crazy/url/<%=h[:day]%>/<%=h[:month]%>/<%=h[:year]%>"
puts template.result(binding)