29

I have an array of strings, and want to make a hash out of it. Each element of the array will be the key, and I want to make the value being computed from that key. Is there a Ruby way of doing this?

For example:

['a','b'] to convert to {'a'=>'A','b'=>'B'}

2
  • Are strings unique? What if they are not? Do you want an exception? Commented Feb 24, 2012 at 16:15
  • yes they will be unique. If they are not I would do a uniq before that. Commented Feb 24, 2012 at 16:19

9 Answers 9

56

You can:

a = ['a', 'b']
Hash[a.map {|v| [v,v.upcase]}]
Sign up to request clarification or add additional context in comments.

1 Comment

this certainly works... but i don't think it's the most efficient... you're iterating twice in this case. Not a concern of course with an array of length 2, but still worth noting.
21
%w{a b c}.reduce({}){|a,v| a[v] = v.upcase; a}

1 Comment

I like your solution! Very slick!
9

Ruby's each_with_object method is a neat way of doing what you want

['a', 'b'].each_with_object({}) { |k, h| h[k] = k.upcase }

Comments

8

From Rails 6.x, you can use Enumerable#index_with:

irb(main):002:0> ['a', 'b'].index_with { |s| s.upcase }
=> {"a"=>"A", "b"=>"B"}

1 Comment

If you derive the key by calling single method, you can use even shorter version: ['a','b'].index_with(&:upcase)
6

Here's another way:

a.zip(a.map(&:upcase)).to_h

#=>{"a"=>"A", "b"=>"B"}

Comments

5

Which ever way you look at it you will need to iterate the initial array. Here's another way :

a = ['a', 'b', 'c']
h = Hash[a.collect {|v| [v, v.upcase]}]
#=> {"a"=>"A", "b"=>"B", "c"=>"C"}

Comments

5

Pass a block to .to_h

[ 'a', 'b' ].to_h{ |element| [ element, element.upcase ] }
#=> {"a"=>"A", "b"=>"B"}

Thanks to @SMAG for the refactor suggestion!

4 Comments

you can just pass the block directly to to_h [ 'a', 'b' ].to_h { |element| [ element, element.upcase ] }
@SMAG Oh damn, that's slick. Did they recently add this, or do you know which version of Ruby it was added in?
looks like it was added some time between 2.3 and 2.7, from the link I provided, but not sure how to get any more specific than that.
@SMAG That's good enough. Looks like it's been around quite a while and people can refer to your comment for a rough idea of minimum version requirement. Thanks for looking into.a
4

Here's a naive and simple solution that converts the current character to a symbol to be used as the key. And just for fun it capitalizes the value. :)

h = Hash.new
['a', 'b'].each {|a| h[a.to_sym] = a.upcase}
puts h

# => {:a=>"A", :b=>"B"}

Comments

1

Not sure if this is the real Ruby way but should be close enough:

hash = {}
['a', 'b'].each do |x|
  hash[x] = x.upcase
end

p hash  # prints {"a"=>"A", "b"=>"B"}

As a function we would have this:

def theFunk(array)
  hash = {}
  array.each do |x|
    hash[x] = x.upcase
  end
  hash
end


p theFunk ['a', 'b', 'c']  # prints {"a"=>"A", "b"=>"B", "c"=>"C"}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.