Reputation: 137
I am trying to convert this array:
["dog", 5 , "big house"]
to hash:
{"dog" => 3 , 5 => 25, "big house" => 9}
The value will be the number of characters of the string (key). If it's an integer (key), then the value will be to the power of 2.
This is what I got so far, but it only converts the string (key):
h = {}
arr.each do |x,y|
y = x.length
h[x] = y
end
Upvotes: 2
Views: 156
Reputation: 247
arr= ["dog", 5, "big house"]
two_dimensional_array = arr.zip(arr.map do |e|
case e
when String then e.length
when Integer then e ** 2
else raise 'Neither string nor numeric given'
end
end)
my_hash = Hash[*two_dimensional_array.flatten]
Upvotes: 0
Reputation: 95385
You can use the Hash[...]
constructor to convert an array of [key, value] pairs to a Hash. So here's another option:
arr = ["dog", 5, "big house"]
result = Hash[ arr.map { |e| [e, e.to_i == e ? e**2 : e.length] } ]
# => {"dog"=>3, 5=>25, "big house"=>9}
Since Ruby 2, you can use Array#to_h
to do the same thing:
result = arr.map { |e| [e, e.to_i == e ? e**2 : e.length] }.to_h
# => {"dog"=>3, 5=>25, "big house"=>9}
Upvotes: 1
Reputation: 8831
You can use inject method.
is_a? method can judge the element is String or Integer.
["dog", 2 , "big house"].inject({}) do |sum, e|
if e.is_a? Integer
sum.merge({e => e*e})
elsif e.is_a? String
sum.merge({e => e.length})
end
end
=> {"dog"=>3, 2=>4, "big house"=>9}
as @Myst said, h[:key] = value
has better performance than merge
, so you also can do like this:
["dog", 2 , "big house"].inject({}) do |sum, e|
if e.is_a? Integer
sum[e] = e*e
elsif e.is_a? String
sum[e] = e.length
end
sum
end
Upvotes: 0
Reputation: 257
You could use the Enumberable#each_with_object method like so:
array = ["dog",5,"big house"]
array.each_with_object({}) {|x,hash| x.is_a?(String) ? hash[x] = x.length : hash[x] = x**2}
# => {"dog"=>3,5=>25,"big house"=>9}
The each_with_object method is very similar to the inject method, so it'll iterate through the array, then once completed it'll return the newly given object. The difference between each_with_object and inject is that each_with_object is immutable, so you can't do something like:
(1..5).each_with_object(0) {|num,sum| sum += num}
It'll only return a zero.
Upvotes: 1
Reputation: 121010
▶ arr = ["dog", 5, "big house"]
#⇒ [ "dog", 5, "big house" ]
▶ arr.zip(arr.map do |e|
▷ case e
▷ when String then e.length
▷ when Integer then e ** 2
▷ else raise 'Neither string nor numeric given'
▷ end
▷ end).to_h
#⇒ { "dog" => 3, 5 => 25, "big house" => 9 }
Upvotes: 2
Reputation: 534
If you have the following array:
arr = ["dog", 5, "big house"]
First you can create a method to convert elements into your desired format based on the element's class:
def convert_to_hash_val(element)
case element
when Fixnum
element**2
else
element.size
end
end
Then create an array of [element, converted_element]
pairs and use the Hash#[] function to convert this to key, value pairs:
Hash[ arr.map {|element| [element, convert_to_hash_val(element)]} ]
# => { "dog" => 3, 5 => 25, "big house" => 9 }
Upvotes: 0
Reputation: 127
result_hash = {}
arr = ["dog", 2, "big house"]
arr.each do |el|
if el.is_a?(String)
result_hash[el] = el.length
elsif el.is_a?(Fixnum)
result_hash[el] = el ** 2
end
end
Remember that the each
block called on an array only throws one argument into the block, which is the currently iterated element.
Upvotes: -1