operador estructuras diferente condicionales ruby hash conditional

ruby - estructuras - Construyendo un hash de una manera condicional



estructuras condicionales en ruby (10)

La misma idea que Chris Jester-Young, con un ligero truco de legibilidad

def cond(x) condition ? x : :delete_me end hash = { :key1 => value1, :key2 => cond(value2), :key3 => value3 }

y luego postprocesar para eliminar las entradas :delete_me

Estoy usando Ruby on Rails 3.0.10 y me gustaría construir una clave hash / pares de valor de una manera condicional. Es decir, me gustaría agregar una clave y su valor relacionado si se cumple una condición:

hash = { :key1 => value1, :key2 => value2, # This key2/value2 pair should be added only ''if condition'' is ''true'' :key3 => value3, ... }

¿Cómo puedo hacer eso y mantener una "buena" legibilidad para el código? ¿Estoy "forzado" a usar el método de merge ?


Mantenlo simple:

hash = { :key1 => value1, :key3 => value3, ... } hash[:key2]=value2 if condition

De esta manera, también separe visualmente su caso especial, que podría pasar desapercibido si está enterrado dentro de la asignación literal hash.


Prefiero el tap , ya que creo que proporciona una solución más limpia que las que se describen aquí al no requerir la eliminación de elementos de hacky y al definir claramente el alcance en el que se está construyendo el hash.

También significa que no necesita declarar una variable local innecesaria, que siempre odio.

En caso de que no lo haya encontrado antes, tap es muy simple: es un método en Object que acepta un bloque y siempre devuelve el objeto al que se llamó. Entonces, para construir un hash condicionalmente podrías hacer esto:

Hash.new.tap do |my_hash| my_hash[:x] = 1 if condition_1 my_hash[:y] = 2 if condition_2 ... end

Hay muchos usos interesantes para el tap , este es solo uno.


Primero compila tu hash de esta manera:

hash = { :key1 => value1, :key2 => condition ? value2 : :delete_me, :key3 => value3 }

Luego haz esto luego de construir tu hash:

hash.delete_if {|_, v| v == :delete_me}

A menos que su hash esté congelado o sea inmutable, esto solo mantendría los valores que están presentes.


Probablemente sea mejor que sea sencillo si le preocupa la legibilidad:

hsh = {} hsh[:key1] = value1 hsh[:key2] = value2 if condition? hsh[:key3] = value3 ...


SI construye hash a partir de algún tipo de datos de Enumerable, puede usar inyectar, por ejemplo:

raw_data.inject({}){ |a,e| a[e.name] = e.value if expr; a }


Tan simple como esto:

hash = { :key1 => value1, **(condition ? {key2: value2} : {}) }

¡Espero eso ayude!


Un enfoque funcional:

hash = { :key1 => 1, :key2 => (2 if condition), :key3 => 3, }.reject { |k, v| v.nil? }

[editar] Ruby 2.4.0 introdujo Hash#compact , por lo que ahora podemos escribir hash = { ... }.compact .


Usar fetch puede ser útil si está poblando un hash de atributos opcionales en otro lugar. Mira este ejemplo:

def create_watchable_data(attrs = {}) return WatchableData.new({ id: attrs.fetch(:id, ''/catalog/titles/breaking_bad_2_737''), titles: attrs.fetch(:titles, [''737'']), url: attrs.fetch(:url, ''http://www.netflix.com/shows/breaking_bad/3423432''), year: attrs.fetch(:year, ''1993''), watchable_type: attrs.fetch(:watchable_type, ''Show''), season_title: attrs.fetch(:season_title, ''Season 2''), show_title: attrs.fetch(:id, ''Breaking Bad'') }) end


Yo uso merge y el operador ternario para esa situación,

hash = { :key1 => value1, :key3 => value3, ... }.merge(condition ? {:key2 => value2} : {})