40

I have looked at other questions in SO and did not find an answer for my specific problem.

I have an array:

a = ["a", "b", "c", "d"]

I want to convert this array to a hash where the array elements become the keys in the hash and all they the same value say 1. i.e hash should be:

{"a" => 1, "b" => 1, "c" => 1, "d" => 1}

10 Answers 10

72

My solution, one among the others :-)

a = ["a", "b", "c", "d"]
h = Hash[a.map {|x| [x, 1]}]
Sign up to request clarification or add additional context in comments.

Comments

34

There are several options:

  • to_h with block:

    a.to_h { |a_i| [a_i, 1] }
    #=> {"a"=>1, "b"=>1, "c"=>1, "d"=>1}
    
  • product + to_h:

    a.product([1]).to_h
    #=> {"a"=>1, "b"=>1, "c"=>1, "d"=>1}
    
  • transpose + to_h:

    [a,[1] * a.size].transpose.to_h
    #=> {"a"=>1, "b"=>1, "c"=>1, "d"=>1}
    

Comments

5
a = ["a", "b", "c", "d"]

4 more options, achieving the desired output:

h = a.map{|e|[e,1]}.to_h
h = a.zip([1]*a.size).to_h
h = a.product([1]).to_h
h = a.zip(Array.new(a.size, 1)).to_h

All these options rely on Array#to_h, available in Ruby v2.1 or higher

Comments

4
a = %w{ a b c d e }

Hash[a.zip([1] * a.size)]   #=> {"a"=>1, "b"=>1, "c"=>1, "d"=>1, "e"=>1}

Comments

4

If your project includes Rails 6 or newer (or you are willing to import ActiveSupport), then you can use Enumerable#index_with:

%i[a b c].index_with { 0 }

# => {a: 0, b: 0, c: 0}

You can optionally pass the array element into the block:

%w[a b c].index_with { |x| x.upcase }

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

Comments

3
["a", "b", "c", "d"].inject({}) do |hash, elem|
  hash[elem] = 1
  hash
end

4 Comments

each_with_object would be a better fit here.
@muistooshort It definitely would be, but it's not something I've used enough for it to come to mind when I'm coding. Thanks! :)
I use it a lot as that extra return value in the block looks lonely :)
@muistooshort And more importantly I always forget it and then get undefined method []= at first :P
3

Here:

hash = Hash[a.map { |k| [k, value] }]

This assumes that, per your example above, that a = ['a', 'b', 'c', 'd'] and that value = 1.

3 Comments

You don't need the flatten, Hash[] can take an Array of Arrays.
Hash[] doesn't seem to take an array of arrays unfortunately: Hash[ [1, 2], [3, 4] ] => {[1, 2]=>[3, 4]}
@AsfandYarQazi: Just do this then: Hash[ *[[1, 2], [3, 4]].flatten ]
0
a = ["a", "b", "c", "d"]
h = a.inject({}){|h,k| h[k] = 1; h}
#=> {"a"=>1, "b"=>1, "c"=>1, "d"=>1}

Comments

0
a = ['1','2','33','20']

Hash[a.flatten.map{|v| [v,0]}.reverse]

Comments

0
{}.tap{|h| %w(a b c d).each{|x| h[x] = 1}}

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.