Creating Ruby Hashes

No Gravatar

I just created a quick Ruby screencast on creating hashes. I don’t cover all of the possibilities, but I do show 5 ways—including one you should never use. Let me know what you think, and if you have questions or ideas for a future screencast, chime in!

Ruby Hashes from David Brady on Vimeo.

Leave a comment ?

23 Comments.

  1. The fourth option brings up a good point that I think catches everyone off guard the first time they use Ruby – shallow copies. That’s the first thing I tell people.

  2. Got a laugh about your perl comment at 1:36. It’s all true. Thanks for explaining method five; That’s been bothering me (I’m a total Roob-n00b.

    Bob, Carol, *Dave* and Alice? I really don’t want to see your Netflix queue.

    • Heh, I’m not even sure what that means… In cryptography jargon, when you say Alice and Bob everyone knows you’re talking about two people who want to have an encrypted conversation. Carol and Dave are two more people, used in examples when you need more than 2 people. After that, everybody else has a name that matches their role: Trent Trustworthy, Eve Eavesdropper, Mallory Malicious, Peggy Prover, Victor Verifier, etc. Or you can just continue alternating boy and girl names (Eddie, Fran, George, Harriet) like hurricanes. :-)

  3. Thanks for showing this, I had forgotten about this little cool corner of Ruby hashes and can’t wait to couple it with inject to create some fun one-liners :twisted:

  4. Nice and in-depth, just the way I like it :-)

    I think you missed one though, unless I looked away and missed where you demonstrated it:


    ruby-1.8.7-p302 > Hash["foo", 1, "bar", 2, "baz", 3]
    {
    "baz" => 3,
    "foo" => 1,
    "bar" => 2
    }

    Combined with splat, this is handy for transforming arrays to hashes:

    ruby-1.8.7-p302 > a = ["foo", 1, "bar", 2, "baz", 3]
    [
    [0] "foo",
    [1] 1,
    [2] "bar",
    [3] 2,
    [4] "baz",
    [5] 3
    ]
    ruby-1.8.7-p302 > Hash[*a]
    {
    "baz" => 3,
    "foo" => 1,
    "bar" => 2
    }

    • Hah, you’re actually getting ahead of me. :-) I left that one out for now, only because it was the weird Kernel#Hash method instead of standard Hash.new. However, James Edward Gray II has also taken me to task for this, and we’re going to record a followup to it tomorrow. I’m really looking forward to it–I’ll let you know as soon as it’s up!

  5. Great screencast! Please post more! Especially since Ryan Bates tackles Rails it would be nice to have the same for pure Ruby.

  6. owner_pet_pairs = [ ["Alice", "Fido"], ["Alice", "Chloe"], ["Bob", "BamBam"] ]
    p owner_pet_pairs.inject(Hash.new { [] } ) { |h, pair| h[pair.first] <<= pair.last; h }

    • Yeah, the inject->hash builder is a bit advanced for the level I was aiming at, but it’s a good tool. I just finished a followup screencast with James Edward Gray II, and he showed me how to build a hash like this in Ruby 1.9, and it’s MUCH cleaner. Definitely worth checking out. I should have that video up tomorrow. Thanks!

  7. Great work,

    I learned this lesson the hard way. I agree with cbmeeks to have something similar to railscast for ruby.

  8. John F. Miller

    Good Cast, but you should learn the inject method. Try it you’ll like it.

    • Yep! I know it, but wanted to hold it back here because this screencast was more aimed at beginners. Also, though, don’t you think that the inject method is just a little bit gratuitously clever? I use it rarely enough that it hasn’t moved up to an immediately recognizable pattern in my brain so I don’t think of it as idiomatic.

      Ooh, be sure to check out the followup screencast I did with James Edward Gray II on Associative Arrays and Ruby Hashes in 1.9, at about 19:55 he shows off the each_with_object method in 1.9. It makes all of the gratuitousness of the inject method go away, but leaves all of the cleverness and elegance. It’s really slick.

      Thanks!

  9. Great screencast – really informative – looking forward to your next one

  10. Just to say thanks, very clear and interesting :)

  11. Histogram! I was using a combo of inject and push on an array to build up a array of hashes for a “histogram” through the Boson framework – I was a calling it a tally by file date/time stamp. Initializing that hash’s members to zero was pure beauty. What was even more mindblowing is when I found I could output the result in descending order just by doing h.to_a.reverse and boson had no problem dealing with associative arrays. Winning!

  12. I occasionally see people do something related to your fourth method (which is actually just the third method, except you’re expecting different behaviour), but without the hash.

    I want to create an NxM matrix full of zeros to do some cool stuff with. An obvious naive (but broken) method is this:

    >> matrix = [[0] * 2] * 3
    => [[0, 0], [0, 0], [0, 0]]

    Of course, this means that you’re using the same array for each row:

    >> matrix[0][0] = 1
    => 1
    >> matrix
    => [[1, 0], [1, 0], [1, 0]]

    I generally use list comprehensions to get around this in Python:

    In [2]: matrix = [[0] * 2 for _ in range(3)]

    In [3]: matrix
    Out[3]: [[0, 0], [0, 0], [0, 0]]

    In [4]: matrix[0][0] = 1

    In [5]: matrix
    Out[5]: [[1, 0], [0, 0], [0, 0]]

    Is there a concise Ruby idiom for it?

    • You mean like:

      Array.new(3, Array.new(2,0))

      Arguably not super-concise, but effective.

    • I will sometimes (ab)use maps for this:

      irb(main):005:0> ray = (0..2).map { [0] * 3}
      => [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
      irb(main):006:0> ray[1][1] = 9
      => 9
      irb(main):007:0> ray
      => [[0, 0, 0], [0, 9, 0], [0, 0, 0]]

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackbacks and Pingbacks: