2016-02-18 3 views
1

Я пытаюсь преобразовать двумерный массив в массив хешей. Вот мой массив:Преобразование массива массивов в массив хэшей в Ruby

[[8765, 105191, 2.0, 1582.1], [4321, 62870, 2.0, 603.24], [1234, 62870, 2.0, 500.24]] 

Я пытаюсь преобразовать это массив значений хэша. Что-то вроде этого:

[{"sales_user_id"=>"8765", "user_id"=>"105191", "month"=>"2", "sum"=>"1582.1"}, 
{"sales_user_id"=>"4321", "user_id"=>"62870", "month"=>"2", "sum"=>"603.24"}, 
{"sales_user_id"=>"1234", "user_id"=>"62870", "month"=>"2", "sum"=>"500.24"}] 

Я разбиваю каждый массив и назначая ключ значениям в массиве. Я все еще немного новичок в рубине, и я не уверен, с чего начать.

+0

Ваш исходный массив имеет Float в третьей позиции, но ваш желаемый результат имеет значения Fixnum для 'month'. Это верно? Вы хотите конвертировать? –

ответ

3

Это довольно просто с Enumerable#zip:

values = [ [ 8765, 105191, 2.0, 1582.1 ], 
      [ 4321, 62870, 2.0, 603.24 ], 
      [ 1234, 62870, 2.0, 500.24 ] ] 
keys = %w[sales_user_id user_id month sum] 

p values.map {|arr| keys.zip(arr).to_h } 
# => [ { "sales_user_id" => 8765, "user_id" => 105191, "month" => 2.0, "sum" => 1582.1 }, 
#  { "sales_user_id" => 4321, "user_id" => 62870, "month" => 2.0, "sum" => 603.24 }, 
#  { "sales_user_id" => 1234, "user_id" => 62870, "month" => 2.0, "sum" => 500.24 } ] 
+0

Если вы используете pre-2.x Ruby, замените 'keys.zip (arr) .to_h' на' Hash [* keyss.zip (arr)] '. –

+0

Ничего себе, у рубина много опрятных инструментов! Спасибо! – learningruby347

0
arr = [[8765, 105191, 2.0, 1582.1 ], 
     [4321, 62870, 2.0, 603.24], 
     [1234, 62870, 2.0, 500.24]] 

keys = ["sales_user_id", "user_id", "month", "sum"] 

Первый способ

[keys].product(arr).map { |a| a.transpose.to_h } 
    #=> [{"sales_user_id"=>8765, "user_id"=>105191, "month"=>2.0, "sum"=>1582.1}, 
    # {"sales_user_id"=>4321, "user_id"=> 62870, "month"=>2.0, "sum"=>603.24}, 
    # {"sales_user_id"=>1234, "user_id"=> 62870, "month"=>2.0, "sum"=>500.24}] 

шаги:

enum = [keys].product(arr) 
    #=> #<Enumerator: 
    #  [ 
    #  [["sales_user_id", "user_id", "month", "sum"], [8765, 105191, 2.0, 1582.1]], 
    #  [["sales_user_id", "user_id", "month", "sum"], [4321, 62870, 2.0, 603.24]], 
    #  [["sales_user_id", "user_id", "month", "sum"], [1234, 62870, 2.0, 500.24]] 
    #  ]:map> 

a = enum.next 
    #=> [["sales_user_id", "user_id", "month", "sum"], [8765, 105191, 2.0, 1582.1]] 
c = a.transpose 
    #=> [["sales_user_id", 8765], ["user_id", 105191], ["month", 2.0], ["sum", 1582.1]] 
c.to_h 
    #=> {"sales_user_id"=>8765, "user_id"=>105191, "month"=>2.0, "sum"=>1582.1} 

a = enum.next 
    #=> [["sales_user_id", "user_id", "month", "sum"], [4321, 62870, 2.0, 603.24]] 
c = a.transpose 
    #=> [["sales_user_id", 4321], ["user_id", 62870], ["month", 2.0], ["sum", 603.24]] 
c.to_h 
    #=> {"sales_user_id"=>4321, "user_id"=>62870, "month"=>2.0, "sum"=>603.24} 

a = enum.next 
    #=> [["sales_user_id", "user_id", "month", "sum"], [1234, 62870, 2.0, 500.24]] 
c = a.transpose 
    #=> [["sales_user_id", 1234], ["user_id", 62870], ["month", 2.0], ["sum", 500.24]] 
c.to_h 
    #=> {"sales_user_id"=>1234, "user_id"=>62870, "month"=>2.0, "sum"=>500.24} 

Второй способ

arr.map do |a| 
    ad = a.dup 
    { "sales_user_id"=>ad.shift, "user_id"=>ad.shift, "month"=>ad.shift, "sum"=>ad.shift } 
end 
    #=> [{"sales_user_id"=>8765, "user_id"=>105191, "month"=>2.0, "sum"=>1582.1}, 
    # {"sales_user_id"=>4321, "user_id"=> 62870, "month"=>2.0, "sum"=>603.24}, 
    # {"sales_user_id"=>1234, "user_id"=> 62870, "month"=>2.0, "sum"=>500.24}] 
0

рассмотреть также с помощью STRUCT, если у вас есть фиксированный набор значений каждого объекта. Может использоваться как хэш.

User = Struct.new(:sales_user_id, :user_id, :month, :sum) 

array = [[8765, 105191, 2.0, 1582.1], [4321, 62870, 2.0, 603.24], [1234, 62870, 2.0, 500.24]] 

users = array.map {|values| User.new *values} 

p users #=> [#<struct User sales_user_id=8765, user_id=105191, month=2.0, sum=1582.1>, #<struct User sales_user_id=4321, user_id=62870, month=2.0, sum=603.24>, #<struct User sales_user_id=1234, user_id=62870, month=2.0, sum=500.24>] 


p users.first.user_id #=> 105191 
p users.first['user_id'] #=> 105191 
p users.first[:user_id] #=> 105191 
0

Вот один из способов сделать это, который использует .collect перебрать внешний массив и построить хэш для каждого внутреннего массива:

values = [[8765, 105191, 2.0, 1582.1], 
      [4321, 62870, 2.0, 603.24], 
      [1234, 62870, 2.0, 500.24]] 

result = values.collect do |array| 
    { 
    "sales_user_id" => array[0].to_s, 
    "user_id" => array[1].to_s, 
    "month" => array[2].to_i.to_s, 
    "sum" => array[3].to_s 
    } 
end 

result:

[{"sales_user_id"=>"8765", "user_id"=>"105191", "month"=>"2", "sum"=>"1582.1"}, 
{"sales_user_id"=>"4321", "user_id"=>"62870", "month"=>"2", "sum"=>"603.24"}, 
{"sales_user_id"=>"1234", "user_id"=>"62870", "month"=>"2", "sum"=>"500.24"}] 

Он также использует .to_s и .to_i, чтобы заставить результат в значениях в вопросе (например, 8765 - "8765" и 2.0 - "2").

Смежные вопросы