Ruby 1.9正则表达式作为哈希键

时间:2011-03-15 11:32:07

标签: ruby regex hash

我正在使用 ruby​​ 1.9.2p136(2010-12-25)[i386-mingw32] 尝试此示例myhash = {/(\d+)/ => "hello"}
它没有按预期工作(编辑:因为事实证明它不应该像我期望的那样工作):

irb(main):004:0> myhash = {/(\d+)/ => "hello"}
=> {/(\d+)/=>"Hello"}
irb(main):005:0> myhash[2222]
=> nil
irb(main):006:0> myhash["2222"]
=> nil

Rubular的ruby1.8.7上regex正常工作 我错过了什么?

5 个答案:

答案 0 :(得分:12)

你在寻找这种行为吗?

myhash = Hash.new{|h,k| h[k] = 'hello' if k =~ /(\d+)/}

p myhash['aaa'] #=> nil
p myhash #=> {}
p myhash['1234'] #=>" hello"
p myhash #=> {"1234"=>"hello"}

答案 1 :(得分:9)

如果没有一些额外的代码,它将无法工作,因为您正在将Regexp对象与Integer或String对象进行比较。它们不是平等的,也不是平等的。它们会匹配,但需要更改Hash类代码。

irb(main):001:0> /(\d+)/.class
=> Regexp
irb(main):002:0> 2222.class
=> Fixnum
irb(main):003:0> '2222'.class
=> String
irb(main):004:0> /(\d+)/==2222
=> false
irb(main):007:0> /(\d+)/=='2222'
=> false
irb(main):009:0> /(\d+)/.equal?'2222'
=> false
irb(main):010:0> /(\d+)/.equal?2222
=> false

你必须迭代哈希并使用=〜之类的东西:

 hash.each do |k,v|    
   unless (k=~whatever.to_s).nil?
     puts v   
   end
 end

或将Hash类更改为try =〜以及正常匹配条件。 (我认为最后一个选项很难,在mri中Hash类似乎有很多C代码)

答案 2 :(得分:3)

您可以将Jean的答案放在default_proc

MAP = {
  /1/ => "one",
  /2/ => "two",
  /\d/ => "number"
}

MAP.default_proc = lambda do |hash, lookup|
  hash.each_pair do |key, value|
    return value if key =~ lookup
  end
  return nil
end

p MAP["2"] #=> "two"
p MAP[44] #=> "number"

答案 3 :(得分:1)

我从未想过使用正则表达式作为哈希键。老实说,我不确定这是否应该有效,也不确定它应该如何运作。

无论如何,有两点想法:

  1. 在您尝试查找该项目时,您使用hash,但该哈希名为myhash
  2. 如果我玩它,我会得到这些结果:

    hektor ~ ❯❯ irb
    >> myhash = {/(\d+)/ => "hello"}
    => {/(\d+)/=>"hello"} 
    >> myhash['2222']
    => nil 
    >> myhash[2222]
    => nil 
    >> myhash[/(\d+)/]
    => "hello" 
    
  3. 这是使用Ruby 1.9.2-p180。

    好的,检查过,这是有效的:

    myhash = {/foo/ => "hello"}
    myhash[/foo/] # => "hello"
    

    查找在密钥上,密钥是正则表达式,而不是该正则表达式的许多潜在匹配之一。

答案 4 :(得分:0)

现在有一个名为Hashie的宝石提供此功能(以及更多):https://github.com/intridea/hashie#rash

它提供了一个名为Rash(regex-hash的缩写)的数据结构,可以像这样使用

myhash = {/(\d+)/ => "hello"}
rash = Hashie::Rash.new(myhash)

>> rash["2222"]
=> "hello"

它确实尝试将键与正则表达式匹配,因此除非将它们转换为字符串,否则数字键将无法工作,您可以通过将Rash继承到您自己的类中轻松完成