metodos manejo hashes datos cadenas array agregar acceder ruby string hashmap symbol

manejo - variables en ruby



¿Por qué usar símbolos como teclas hash en Ruby? (4)

Muchas veces las personas usan símbolos como claves en un hash Ruby.

¿Cuál es la ventaja sobre el uso de una cadena?

P.ej:

hash[:name]

vs.

hash[''name'']


Estaría muy interesado en un seguimiento sobre las cadenas congeladas introducidas en Ruby 2.x.

Cuando trabajas con numerosas cadenas provenientes de una entrada de texto (estoy pensando en HTTP params o payload, a través de Rack, por ejemplo), es mucho más fácil usar cadenas en todas partes.

Cuando trabajas con docenas de ellos pero nunca cambian (si es el vocabulario de tu negocio), me gusta pensar que congelarlos puede marcar la diferencia. Todavía no he hecho ningún punto de referencia, pero supongo que sería el rendimiento de símbolos cerca.


La razón es la eficiencia, con ganancias múltiples sobre una cadena:

  1. Los símbolos son inmutables, por lo que la pregunta "¿qué pasa si la clave cambia?" no necesita ser preguntado.
  2. Las cadenas están duplicadas en su código y, por lo general, ocuparán más espacio en la memoria.
  3. Las búsquedas hash deben calcular el hash de las claves para compararlas. Este es O(n) para Cadenas y constante para Símbolos.

Además, Ruby 1.9 introdujo una sintaxis simplificada solo para hash con las teclas de símbolos (p h.merge(foo: 42, bar: 6) Ej. h.merge(foo: 42, bar: 6) ), y Ruby 2.0 tiene argumentos de palabras clave que funcionan solo para las teclas de símbolos.

Notas :

1) Es posible que se sorprenda al saber que Ruby trata las Cadenas de String diferente a cualquier otro tipo. En efecto:

s = "foo" h = {} h[s] = "bar" s.upcase! h.rehash # must be called whenever a key changes! h[s] # => nil, not "bar" h.keys h.keys.first.upcase! # => TypeError: can''t modify frozen string

Solo para claves de cadena, Ruby usará una copia congelada en lugar del objeto en sí.

2) Las letras "b", "a" y "r" se almacenan solo una vez para todas las apariciones de :bar en un programa. Antes de Ruby 2.2, era una mala idea crear constantemente nuevos Symbols que nunca se reutilizaran, ya que permanecerían en la tabla global de búsqueda de símbolos para siempre. Ruby 2.2 los recogerá la basura, así que no te preocupes.

3) En realidad, calcular el hash para un Símbolo no tomó tiempo en Ruby 1.8.x, ya que el ID del objeto se usó directamente:

:bar.object_id == :bar.hash # => true in Ruby 1.8.7

En Ruby 1.9.x, esto ha cambiado a medida que los valores hash cambian de una sesión a otra (incluidos los de Symbols ):

:bar.hash # => some number that will be different next time Ruby 1.9 is ran


Re: ¿cuál es la ventaja sobre el uso de una cadena?

  • Estilo: es el camino de Ruby
  • (Muy) búsquedas de valor ligeramente más rápidas ya que hash de un símbolo es equivalente a hash un entero versus hash de una cadena.

  • Desventaja: consume un espacio en la tabla de símbolos del programa que nunca se libera.


Respuesta corta:

El uso de símbolos no solo ahorra tiempo al hacer comparaciones, sino que también ahorra memoria, ya que solo se almacenan una vez.

Los símbolos en Ruby son básicamente "cadenas inmutables" ... eso significa que no se pueden cambiar, e implica que el mismo símbolo cuando se hace referencia a él a lo largo de su código fuente, siempre se almacena como la misma entidad, por ejemplo, tiene el mismo ID de objeto .

Las cadenas, por otro lado, son mutables , se pueden cambiar en cualquier momento. Esto implica que Ruby necesita almacenar cada cadena que mencione a lo largo de su código fuente en su entidad separada, por ejemplo, si tiene un "nombre" de cadena varias veces mencionado en su código fuente, Ruby necesita almacenarlos todos en objetos String separados, porque podría cambiar más adelante (esa es la naturaleza de una cadena de Ruby).

Si usa una cadena como una tecla Hash, Ruby necesita evaluar la cadena y ver su contenido (y calcular una función hash) y comparar el resultado con los valores (hash) de las claves que ya están almacenadas en la Hash .

Si usa un símbolo como una tecla Hash, está implícito que es inmutable, por lo que Ruby básicamente puede hacer una comparación de la función (función hash de) id-objeto contra los identificadores-objeto (hash) de claves que ya están almacenadas en el Hash. (mucho mas rápido)

Desventaja: cada símbolo consume una ranura en la tabla de símbolos del intérprete de Ruby, que nunca se libera. Los símbolos nunca se recogen basura. Por lo tanto, un caso de esquina es cuando tienes una gran cantidad de símbolos (p. Ej., Autogenerados). En ese caso, debe evaluar cómo esto afecta el tamaño de su intérprete de Ruby.

Notas:

Si realiza comparaciones de cadenas, Ruby puede comparar símbolos simplemente por sus identificadores de objetos, sin tener que evaluarlos. Eso es mucho más rápido que comparar cadenas, que necesitan ser evaluadas.

Si accede a un hash, Ruby siempre aplica una función hash para calcular una "clave hash" desde cualquier tecla que use. Puedes imaginar algo como un MD5-hash. Y luego Ruby compara esas "claves hash" entre sí.

Respuesta larga:

http://www.reactive.io/tips/2009/01/11/the-difference-between-ruby-symbols-and-strings

http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol