0

I have an Array that contains strings:

["First Name", "Last Name", "Location", "Description"]

I need to convert the Array to a Hash, as in the following:

{"A" => "First Name", "B" => "Last Name", "C" => "Location", "D" => "Description"}

Also, this way too:

{"First Name" => "A", "Last Name" => "B", "Location" => "C", "Description" => "D"}

Any thoughts how to handle this the best way?

4 Answers 4

2

You could implement as follows

 def string_array_to_hash(a=[],keys=false)
    headers = ("A".."Z").to_a
    Hash[keys ? a.zip(headers.take(a.count)) : headers.take(a.count).zip(a)]
 end

Then to get your initial output it would be

 a = ["First Name", "Last Name", "Location", "Description"]
 string_array_to_hash a 
 #=> {"A"=>"First Name", "B"=>"Last Name", "C"=>"Location", "D"=>"Description"}

And second output is

 a = ["First Name", "Last Name", "Location", "Description"]
 string_array_to_hash a, true 
 #=> {"First Name"=>"A", "Last Name"=>"B", "Location"=>"C", "Description"=>"D"}

Note: this will work as long as a is less than 27 Objects otherwise you will have to specify a different desired output. This is due to the fact that a) the alphabet only has 26 letters b) Hash objects can only have unique keys.

Sign up to request clarification or add additional context in comments.

2 Comments

How can I do it without creating a method?
@NicholasAlek you could just define the alphabet as alphabet = ("A".."Z").to_a and then abstract a.zip(alphabet.take(a.count)) and alphabet.take(a.count).zip(a) to get your 2 desired results although I am not sure why you are opposed to a method.
1

You could do this:

arr = ["First Name", "Last Name", "Location", "Description"]

letter = Enumerator.new do |y|
  l = ('A'.ord-1).chr
  loop do
    y.yield l=l.next
  end
end
  #=> #<Enumerator: #<Enumerator::Generator:0x007f9a00878fd8>:each> 

h = arr.each_with_object({}) { |s,h| h[letter.next] = s }
  #=> {"A"=>"First Name", "B"=>"Last Name", "C"=>"Location", "D"=>"Description"} 

h.invert
  #=> {"First Name"=>"A", "Last Name"=>"B", "Location"=>"C", "Description"=>"D"} 

or

letter = ('A'.ord-1).chr
  #=> "@" 
h = arr.each_with_object({}) { |s,h| h[letter = letter.next] = s }
  #=> {"A"=>"First Name", "B"=>"Last Name", "C"=>"Location", "D"=>"Description"} 

When using the enumerator letter, we have

27.times { puts letter.next }
  #=> "A"
  #   "B"
  #   ...
  #   "Z"
  #   "AA"

15 Comments

very nice use of Enumerable#next and inversion (of which I completely forgot about).
Cary, one more question. What's the easier way to retrieve a value from the hash using the above code?
@NicholasAlek this seems like a question that might benefit more from self discovery by looking at the Hash object. There are many methods for retrieval all are very easy.
@engineersmnky, note that 'Z'.next => 'AA'. The Ruby monks are looking out for us.
I cleaned up the construction of the enumerator. (@engineersmnky: of possible interest.)
|
0

If you are not being specific about keys name then you could try this out

 list = ["First Name", "Last Name", "Location", "Description"] 
 Hash[list.map.with_index{|*x|x}].invert

Output

 {0=>"First Name", 1=>"Last Name", 2=>"Location", 3=>"Description"} 

Similar solutions is here.

1 Comment

Thanks hkumar, it needs to have alphabet.
0

Or..You also can try this :)

letter = 'A'
arr = ["First Name", "Last Name", "Location", "Description"]
hash = {}
arr.each { |i|
hash[i] = letter
letter = letter.next
}

// => {"First Name"=>"A", "Last Name"=>"B", "Location"=>"C", "Description"=>"D"} 

or

letter = 'A'
arr = ["First Name", "Last Name", "Location", "Description"]
hash = {}
arr.each { |i|
hash[letter] = i
letter = letter.next
}

// => {"A"=>"First Name", "B"=>"Last Name", "C"=>"Location", "D"=>"Description"} 

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.