Ruby 1.9 Hash with a Dash in a Key

Ruby 1.9 hash with a dash in a key

As of Ruby 2.2, you also can use following syntax:

{a: 1, b: 2, 'c-c': 3, d: 4}

How to set a hash key using a variable in Ruby 1.9?

Let me introduce you two ways to do what you exactly want. If you don't want to continue using 1.8 syntax and hashrockets anymore, ruby-doc.org recommends doing it in this way in Ruby 1.9.3:

my_hash = Hash.new

my_key = "key000"
my_hash[my_key] = "my_value"

Livedemo: http://ideone.com/yqIx2M

Second one (more similar to what you are trying to achieve) is:

my_key = "key0"
my_hash = Hash[my_key, "value00"]

puts my_hash

Livedemo: http://ideone.com/HHLyAi

How to escape a dash - in a Ruby symbol?

Use single quotes around the symbol name, with the colon prefix:

:'data-role' => 'button'

And here is a nice reference on symbols:

http://www.troubleshooters.com/codecorn/ruby/symbols.htm#_What_do_symbols_look_like

After Ruby 1.9 you can also do

'data-role': 'button'

Why can't I use an integer as a key using the new Ruby 1.9.2 hash syntax?

This syntax is only for Ruby 'symbols', and is an alternative to the common usage:

:symbol => 5

rather than as a general key. More on symbols here. And others have written about this with respect to the principal of least surprise (see here).

Ruby 1.9: turn these 4 arrays into hash of key/value pairs

I would probably do it like this

# assuming names, fav_colors, birth_dates, and locations are your arrays

name_collection = {}

names.zip(birth_dates, fav_colors, locations) do |name, birth_date, fav_color, location|
name_collection[name] = { :birth_date => birth_date,
:fav_color => fav_color,
:location => location }
end

# usage
puts name_collection['jack'][:fav_color] # => 'blue'

Sorting a Hash by integer value of hash key in Ruby 1.9

Nice and simple (for 1.9):

hs = Hash[h.sort_by {|k,v| k.to_i }]

For example:

>> h = { '23' => 'twenty three', '11' => 'eleven', '42' => 'forty two', '1' => 'one' }
=> {"23"=>"twenty three", "11"=>"eleven", "42"=>"forty two", "1"=>"one"}
>> hs = Hash[h.sort_by {|k,v| k.to_i }]
=> {"1"=>"one", "11"=>"eleven", "23"=>"twenty three", "42"=>"forty two"}

And for more recent Rubies:

hs = h.sort_by { |k, _| k.to_i }.to_h

Is it a bad style of using key: value instead of :key = value in a hash of Ruby 1.9

The Ruby Style Guide says "When the keys of your hash are symbols use the Ruby 1.9 hash literal syntax.".

The main reason I use the 1.8-style syntax is that I currently use a few analysis tools that either don't work on Ruby 1.9 (heckle ... at least not yet) or don't work as well on 1.9 (ruby-prof).

How to create symbol (hash key) from association, using new ruby (1.9) hash syntax?

The JavaScript style syntax is not really the new syntax, it is just an alternate syntax in 1.9 that can be used for some symbol literals within a Hash literal.

You can't use the trailing-colon style with all symbols, try these and you'll see:

{ :$set => 11 }                       # Valid
{ $set: 11 } # Invalid
{ :'where.is.pancakes.house?' => 23 } # Valid
{ 'where.is.pancakes.house?': 23 } # Invalid

Similarly, if you have a symbol that isn't a symbol literal:

s = o.to_sym; { s => 42 }
{ o.to_sym => 42 }

then you have to use the fat arrow syntax in your Hashes. The same applies if you have a key that isn't a symbol:

a = %w{where is pancakes house?}
h = { a => 11 }
g = { a: 11 } # Also works but produces a completely different result!

In summary, the trailing-colon converts some literal values (I think anything that matches /\A[a-z_]\w*\z/i but I'm not certain) that precede it to symbols when used inside a Hash literal. Basically, the JavaScript style is useless in all but the most trivial cases; but the trivial cases do happen to be the most common.

The only way I can think of to use the JavaScript style with a non-literal symbol would be an abomination like this:

ass = association.to_s.singularize.to_sym
h = eval "{ #{ass}: 'pancakes' }"

and if you ever put something like that in real code then may the gods have mercy on your soul.

Also, keep in mind that you have to use the leading-colon form of the symbol when you want to access your hash:

h[:pancakes] # Valid
h[pancakes:] # Invalid

so the JavaScript style is of limited utility.

Supporting Ruby 1.9's hash syntax in Ruby 1.8

I think you're out of luck, if you want to support 1.8 then you have to use =>. As usual, I will mention that you must use => in certain cases in 1.9:

  1. If the key is not a symbol. Remember that any object (symbols, strings, classes, floats, ...) can be a key in a Ruby Hash.
  2. If you need a symbol that you'd quote: :'this.that'.
  3. If you use MongoDB for pretty much anything you'll be using things like :$set => hash but $set: hash is a syntax error.

Back to our regularly scheduled programming.

Why do I say that you're out of luck? The Hash literal syntaxes (both of them) are hard-wired in the parser and I don't think you're going to have much luck patching the parser from your gem. Ruby 1.8.7's parse.y has this to say:

assoc    : arg_value tASSOC arg_value
{
$$ = list_append(NEW_LIST($1), $3);
}
;

and tASSOC is => so hash literals are hard-wired to use =>. 1.9.3's says this:

assoc    : arg_value tASSOC arg_value
{
/*%%%*/
$$ = list_append(NEW_LIST($1), $3);
/*%
$$ = dispatch2(assoc_new, $1, $3);
%*/
}
| tLABEL arg_value
{
/*%%%*/
$$ = list_append(NEW_LIST(NEW_LIT(ID2SYM($1))), $2);
/*%
$$ = dispatch2(assoc_new, $1, $2);
%*/
}
;

We have the fat-arrow syntax again (arg_value tASSOC arg_value) and the JavaScript style (tLABEL arg_value); AFAIK, tLABEL is also the source of the restrictions on what sorts of symbols (no :$set, no :'this.that', ...) can be used with the JavaScript-style syntax. The current trunk parse.y matches 1.9.3 for Hash literals.

So the Hash literal syntax is hard-wired into the parser and you're stuck with fat arrows if you want to support 1.8.



Related Topics



Leave a reply



Submit