如何使用正则表达式匹配哈希对象中的字符串文字符号?

时间:2014-03-27 15:35:38

标签: ruby regex hash

使用str作为哈希中的键可以正常工作。

string = 'The dog and cat'
replace = {'dog' => 'woof', 'cat' => 'meow'}
replace.default = 'unknown'

string.gsub(/\w+/, replace)
 # => "unknown woof unknown meow" 

如何使用sym作为哈希键获得相同的结果?

string = 'The dog and cat'
replace = {dog: 'woof', cat: 'meow'}
replace.default = 'unknown'

string.gsub(/\w+/, replace)
 # => "unknown unknown unknown unknown" (actual result)
 # => "unknown woof unknown meow" using symbols as hash keys? (desired result)

我做了一些尝试:

string.gsub(/(\w+)/, replace[:$1])
 # => "unknown unknown unknown unknown"

string.split.map(&:to_sym).to_s.gsub(/\w+/, replace)
 # => "[:unknown, :unknown, :unknown, :unknown]" 

3 个答案:

答案 0 :(得分:3)

在下面的代码中:

string = 'The dog and cat'
replace = {dog: 'woof', cat: 'meow'}
replace.default = 'unknown'
string.gsub(/\w+/, replace)

您创建了哈希replace,默认值为'unknown'。这意味着,当您从散列replace中查找值时,如果该键不存在,则散列将返回unknown作为值。当你以这种方式定义哈希时,它将以这种方式工作。

现在#gsub方法,将所有单词匹配为'the''dog'等,但这些字符串都不是您的哈希replace的关键,正如我所说如上所述,哈希replace将每次unknown返回默认值。

请记住 - 在哈希replace = {dog: 'woof', cat: 'meow'}中,键是符号,例如:dog:cat。但是#gsub会将所有匹配作为字符串

因此,要使其工作,您需要使用如下的块:

string = 'The dog and cat'
replace = {dog: 'woof', cat: 'meow'}
replace.default = 'unknown'
string.gsub(/\w+/) { |m| replace[m.to_sym] } 
# => "unknown woof unknown meow"

答案 1 :(得分:1)

如果你想保留所有其他单词,但只是替换散列中的内容,你可以这样做:

replace = {'dog' => 'woof', 'cat' => 'meow'}
my_string = 'The dog and cat'
my_string.gsub(/\w+/) {|m| (replace.key? m) ? replace[m] : m}

将产生:

The woof and meow

或更紧凑(感谢@Arup提示):

my_string.gsub(/\w+/) {|m| replace.fetch(m, m)}

答案 2 :(得分:0)

目前尚不清楚为什么要用unknown替换“未知”单词;这在普通的字符串处理或模板处理代码中并不是非常有用。结果,你似乎在问一个X-Y问题,想要知道当你应该做“X”时如何做“Y”。

以下是一些代码和可能有用的信息:

string = 'The dog and cat'
replacement_hash = {dog: 'woof', cat: 'meow'}

首先,要非常小心地使用与方法同名的变量。 Ruby可以弄明白你的意思,但是你的大脑总是无法建立连接。使用或维护代码的人的大脑可能效果不佳。因此,使用类似replace的内容而不是名为replacement_hash的哈希。

通常我们不想使用符号作为键来定义哈希,如果我们要对字符串进行搜索和替换操作。相反,我们想要实际的字符串值;这样更直接。也就是说,这将遍历带符号作为键的哈希,并使用等效字符串作为键生成新哈希:

replacement_hash2 = Hash[replacement_hash.keys.map(&:to_s).zip(replacement_hash.values)] # => {"dog"=>"woof", "cat"=>"meow"}

我们give gsub a regular expression,它会遍历字符串,寻找与该模式匹配的内容。它的一个很酷的功能是我们可以给它一个哈希值,并且对于发现的每个匹配,它将查看相关的哈希并返回匹配键的值。

以下是如何轻松构建与哈希中的键匹配的模式。我使用的是不区分大小写的模式,但是YMMV:

key_regex = /\b(?:#{ Regexp.union(replacement_hash.keys.map(&:to_s)).source })\b/i # => /\b(?:dog|cat)\b/i

在最基本的形式中,这是一个gsub,它使用模式在哈希值中查找值:

string.gsub(key_regex, replacement_hash2) # => "The woof and meow"

也可以使用模式搜索字符串,然后将“命中”传递给一个块,然后计算所需的替换:

string.gsub(key_regex) { |w| replacement_hash2[w] } # => "The woof and meow"

或:

string.gsub(key_regex) { |w| replacement_hash[w.to_sym] } # => "The woof and meow"

但是等等!还有更多!

如果您不想要手术方法,您还可以使用更通用的(“霰弹枪方法”)正则表达式模式,并在查看哈希值时处理命中和未命中:

string.gsub(/\S+/) { |w| replacement_hash[w.to_sym] || 'unknown' } # => "unknown woof unknown meow"

将原始代码转换为单个简单的代码行。根据需要更改正则表达式。

打坐这个是上面块的内容没有意义:

replacement_hash[:dog] # => "woof"
replacement_hash[:foo] # => nil
nil || 'unknown' # => "unknown"

请注意,使用replacement_hash哈希将匹配的可疑/目标词转换为符号非常重要。这可能会变得棘手或复杂,因为某些字符串不会干净地转换为符号并导致双引号。您必须在哈希定义中考虑到这一点:

'foo'.to_sym # => :foo
'foo_bar'.to_sym # => :foo_bar
'foo-bar'.to_sym # => :"foo-bar"
'foo bar'.to_sym # => :"foo bar"