2011-03-15 16 views
10

estoy tratando este ejemplo myhash = {/(\d+)/ => "hello"} con rubí 1.9.2p136 (2010-12-25) [i386-mingw32].
No funciona como se esperaba (edit: como se vio después para que no funcione como esperaba):Ruby 1.9 de expresiones regulares como una clave hash

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

En Rubular que se encuentra en las ruby1.8.7 regex obras.
¿Qué me estoy perdiendo?

+0

'' myhash' vs hash'? – gnab

+0

@gnab - bien manchado. pero desafortunadamente ese no es el problema –

+1

Creo que tienes que iterar el hash y hacer una coincidencia normal. No será rápido aunque. –

Respuesta

9

No funcionará sin un código adicional, ya que está comparando un objeto Regexp con un entero o un objeto String. No tendrán valor igual, ni identidad igual. Coinciden pero eso requiere cambios en el código de clase 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 

que tendría que recorrer el hash y utilizar = ~ en algo así como:

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

o cambiar la clase Hash para tratar = ~ además de las condiciones normales correspondientes. (Creo que la última opción sería difícil, en mri la clase Hash parece tener un montón de código C)

1

Nunca se me ocurrió usar una expresión regular como una clave hash. Sinceramente, no estoy seguro de si eso debería funcionar, ni exactamente cómo funcionaría si así fuera.

En cualquier caso, dos pensamientos:

  1. En sus intentos de buscar el elemento, que utilizan hash, pero el hash se denomina myhash.
  2. Si juego un rato con él, me sale estos resultados:

    hektor ~ ❯❯ irb 
    >> myhash = {/(\d+)/ => "hello"} 
    => {/(\d+)/=>"hello"} 
    >> myhash['2222'] 
    => nil 
    >> myhash[2222] 
    => nil 
    >> myhash[/(\d+)/] 
    => "hello" 
    

Esto es usando Rubí 1.9.2-p180.

Ok, comprobado y esto es lo que funciona:

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

La búsqueda está en la clave, y la clave es una expresión regular, no es uno de los muchos posibles coincidencias de expresiones regulares que.

+0

@Telemachus - yeap myhash & hash fue mi error tipográfico. Y parece que ruby ​​realmente no trata a/(\ d +)/como una expresión regular. –

+0

@Telemachus - me encontré con este mensaje SO http://stackoverflow.com/questions/2082457/ruby-gsub-problem-when-using-backreference-and-hashes. Y parece que debería funcionar. –

+0

la publicación a la que se vincula requiere un iterador y una llamada a gsub que interpretará la expresión regular. En tu caso, estás tratando de combinar un objeto regex con un Entero y una Cadena respectivamente ... – Jean

10

¿Está buscando este comportamiento?

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"} 
3

Usted puede poner la respuesta de Jean en una 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" 
Cuestiones relacionadas