2015-01-12 2 views
0

У меня есть массив, который содержит строки:Преобразовать массив строк в хэш в Ruby,

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

мне нужно, чтобы преобразовать массив в Hash, как в следующем примере:

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

Кроме того, этот способ тоже:

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

Любые мысли, как справиться с этим лучше всего?

ответ

1

Вы можете сделать это:

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"} 

или

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"} 

При использовании нумератор letter мы имеем

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

Ты потрясающий Кэри! Благодаря! –

+0

очень приятное использование 'Enumerable # next' и inversion (о котором я совсем забыл). – engineersmnky

+0

Cary, еще один вопрос.Каков более простой способ получить значение из хэша, используя вышеуказанный код? –

2

Вы могли бы осуществить следующим образом

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 

Затем, чтобы получить ваш первоначальный вывод было бы

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

И второй выход

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

Примечание: это будет работать до тех пор, пока a составляет менее 27 обь В противном случае вам нужно будет указать другой желаемый результат. Это связано с тем, что: а) алфавит имеет только 26 букв; б) объекты хэши могут иметь только уникальные ключи.

+0

Благодаря @engineersmnky. Попробуй. –

+0

Как это сделать без создания метода? –

+0

@NicholasAlek вы можете просто определить алфавит как 'alphabet = (" A ".." Z "). To_a', а затем абстрактный' a.zip (alphabet.take (a.count)) 'и' alphabet.take (a.count) .zip (a) ', чтобы получить 2 желаемых результата, хотя я не уверен, почему вы против метода. – engineersmnky

0

Если вы не специфичен о наименовании ключей, то вы могли бы попробовать это

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

Выход

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

Аналогичные решения является here.

+0

Спасибо hkumar, он должен иметь алфавит. –

0

Or..You также можете попробовать это :)

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"} 

или

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"}