Entonces, quiero crear un hash donde las claves se conviertan en matrices sin tener que declararlas por separado.
Por lo tanto, uso
foo = Hash.new([]) => {}Luego puedo agregar elementos a las claves que no se han declarado previamente
foo[:bar] << 'Item 1' => ['Item 1']Hay algo raro en hacer esto. Como cuando llamo
foo => {}para ver el hash, está vacío. incluso corriendo
foo.keys => []muestra que está vacío. Sin embargo, si corro
foo[:bar] => ['Item 1']Por favor, haz que tenga sentido.
foo = Hash.new([]) establece el valor predeterminado de una clave que no existe en una matriz. Aquí foo[:bar] << 'Item 1' , la tecla :bar no existe, por lo que foo usa una matriz a la que agrega un nuevo elemento. Al hacerlo, muta el valor predeterminado porque la matriz se le proporciona mediante una referencia.
> foo = Hash.new([]) => {} > foo.default => []Si llama a cualquier clave no definida en su hash, obtendrá esta matriz:
> foo[:bar] << 'Item 1' => ["Item 1"] > foo[:foo] => ["Item 1"] Para lograr su objetivo, debe devolver una nueva matriz cada vez. Es posible pasando un bloque a Hash.new , el bloque se ejecutará cada vez que acceda a una clave no definida:
> foo = Hash.new { |hash, key| hash[key] = [] } => {} > foo[:bar] << 'Item 1' => ["Item 1"] > foo[:bar] => ["Item 1"] > foo.keys => [:bar] > foo[:foo] => [] > foo[:foo] << 'Item 2' => ["Item 2"] > foo => {:bar=>["Item 1"], :foo=>["Item 2"]}