2014-09-16 3 views
0

У меня есть массив:Ruby: многомерный массив в многомерном хэш

a = [[1,[2,3]], [2,[3,4]], [3,[4,5]]] 

Я хочу, чтобы преобразовать его в:

h = {1 => {2 => 3}, 2 => {3 => 4}, 3 => {4 => 5}} 

Я новичок в Ruby, может кто-нибудь помочь мне решить эту проблему?

+3

Пожалуйста, покажите, что вы пробовали до сих пор. –

+3

Вы должны проверить синтаксис своего массива, выражение '[2,] [3,4]' оценивается как 'nil', поэтому массив фактически эквивалентен:' [[[1, [2, 3]], nil], [3, [4, 5]]] ', что, вероятно, не то, что вы хотите. – toro2k

+1

Вы контролируете, откуда этот массив? Не могли бы вы изменить код для вывода в требуемом формате? –

ответ

5

Если вы имеете в виду:

a = [[1,[2,3]], [2,[3,4]], [3,[4,5]]] 

Hash[a.map { |k0, (k, v)| [k0, {k => v}] }] 
# => {1=>{2=>3}, 2=>{3=>4}, 3=>{4=>5}} 

a.map { |k0, (k, v)| [k0, {k => v}] }.to_h # Ruby 2.1+ 
# => {1=>{2=>3}, 2=>{3=>4}, 3=>{4=>5}} 
+0

приятный ответ. 1 + –

+0

Да! Я понял. Thanx –

+0

@ChandrikaDesai, Добро пожаловать в переполнение стека! Есть люди, которые пытались ответить на ваш вопрос. Если бы это помогло вам, вы можете рассказать об этом сообществу, приняв ответ [http://meta.stackoverflow.com/a/5235], который был наиболее полезен для вас. – falsetru

0

Другой способ:

a = [[1, [2, 3]], [2, [3, 4]], [3,[4, 5]]] 

a.each_with_object({}) { |(i, (k, v)), h| h[i] = { k => v } } 
#=> {1=>{2=>3}, 2=>{3=>4}, 3=>{4=>5}} 

Вложенные значения извлекаются с помощью разложения массива в Ruby:

[1, [2, 3]] 
(i, (k, v)) 
0

Это может быть реализовано хорошо, как карта/уменьшить:

a = [[1, [2, 3]], [2, [3, 4]], [3,[4, 5]]] 

a.map{|k,v| {k=>v}}.reduce(:merge) 
# => {1=>{2=>3}, 2=>{3=>4}, 3=>{4=>5}} 

карта превращает каждый суб-массив в крошечном хэш, и уменьшить итеративно применяется Hash # слияния, чтобы объединить их в один большой хэш.

Это более красноречиво, чем другие реализации, которые я видел, а также более читаемые/идиоматические (по крайней мере, на мой взгляд).

0

Вот еще один способ, который я предлагаю, потому что: а) стандартные подходы уже упоминались в ранее опубликованных ответах; и б) вы можете найти его поучительным, если не немного странным.

Что мы будем делать это создать пустой хэш h, а затем выполнить:

a.each { |k| h[k] } 

и вуаля!

h => {1=>{2=>3}, 2=>{3=>4}, 3=>{4=>5}} 

«Как это может быть?», Вы, вероятно, думаете. Фокус в том, как мы определяем хеш h; а именно, мы используем форму методы класса Hash::new, который принимает блок:

h = Hash.new { |h,(x,(y,z))| h[x] = { y=>z } } 

Это обычно используется следующим образом:

h = Hash.new { |h,k| h[k] = ... } } 

Это говорит, что, когда h передается ключ k, что уже не в хеше, блок должен быть выполнен для вычисления значения, связанного с новым ключом. Однако нам не нужно использовать k. Здесь я передаю элемент a, который я написал в его разложенной форме (или «disambiguted»), (x,(y,z)), а затем добавив пару ключей-значений x => { y=>z } к хэшу.

Это может быть вместо этого написано:

h = Hash.new { |h,k| h[k.first] = { k.last.first=>k.last.last } } 

, но я надеюсь, вы согласитесь, что разложившийся форма намного легче читать.

Вместо:

h = Hash.new { |h,(x,(y,z))| h[x] = { y=>z } } 
a.each { |k| h[k] } 
h 

более рубин как способ:

a.each_with_object(Hash.new { |h,(x,(y,z))| h[x] = { y=>z } }) { |k,h| h[k] } 
Смежные вопросы