对嵌套数组进行分组并转换为哈希

时间:2016-02-18 03:57:13

标签: arrays ruby hash

我有一个嵌套数组:

array = [
  [8765, 105191, 2.0, 1582.1],
  [4321, 62770, 2.0, 603.24], 
  [4321, 105191, 2.0, 1900.8],
  [1234, 62770, 2.0, 603.24]
]

每个子数组中索引0处的元素是sales_user,我想按此分组。我需要得到它:

[
  [8765, [105191, 2.0, 1582.1]]
  [[4321, [[62770, 2.0, 603.24]], [[105191, 2.0, 1900.8]]]
  [1234, [[62770, 2.0, 603.24]]]
]

我试过这样做:

array.group_by(&:first).map { |c, xs| [c, xs] } 

它几乎给了我想要的东西:

[
  [8765, [[8765, 105191, 2.0, 1582.1]]], 
  [4321, [[4321, 62770, 2.0, 603.24]] [4321, 105191, 2.0, 1900.8]]],
  [1234, [[1234, 62770, 2.0, 603.24]]]
]

但它包含了sales_user在子数组中。

我想将分组数组转换为哈希值。这很容易吗?也许我需要将原始数组转换为哈希值,然后按sales_user进行分组。

3 个答案:

答案 0 :(得分:0)

array.map{| e | { e.first => e.drop(1) }}
=> [{8765=>[105191, 2.0, 1582.1]}, 
    {4321=>[62770, 2.0, 603.24]}, 
    {4321=>[105191, 2.0, 1900.8]}, 
    {1234=>[62770, 2.0, 603.24]}]

我建议这样做:

keys = [ :sales_user, :user_id, :month, :amount]
array.map{|r | r.map.with_index{| e,i | { keys[ i ] => e }}.reduce :merge }
=> [{:sales_user=>8765, :user_id=>105191, :month=>2.0, :amount=>1582.1}, 
    {:sales_user=>4321, :user_id=>62770, :month=>2.0, :amount=>603.24},
    {:sales_user=>4321, :user_id=>105191, :month=>2.0, :amount=>1900.8}, 
    {:sales_user=>1234, :user_id=>62770, :month=>2.0, :amount=>603.24}]

答案 1 :(得分:0)

h = array.group_by(&:first)
  #=> {8765=>[[8765, 105191, 2.0, 1582.1]],
  #    4321=>[[4321, 62770, 2.0, 603.24], [4321, 105191, 2.0, 1900.8]],
  #    1234=>[[1234, 62770, 2.0, 603.24]]}

enum = h.map
  #=> #<Enumerator: {8765=>[[8765, 105191, 2.0, 1582.1]],
  #                  4321=>[[4321, 62770, 2.0, 603.24], [4321, 105191, 2.0, 1900.8]],
  #                  1234=>[[1234, 62770, 2.0, 603.24]]}:map> 

 k,v = enum.next
   #=> [8765, [[8765, 105191, 2.0, 1582.1]]] 
 k #=> 8765 
 v #=> [[8765, 105191, 2.0, 1582.1]] 
 [k, v.size==1 ? v.first : v]
   #=> [8765, [[8765, 105191, 2.0, 1582.1]].size==1 ?
   #=>   [[8765, 105191, 2.0, 1582.1]].first : [[8765, 105191, 2.0, 1582.1]]]
   #=> [8765, true ? [8765, 105191, 2.0, 1582.1] : [[8765, 105191, 2.0, 1582.1]]]          
   #=> [8765, [8765, 105191, 2.0, 1582.1]] 

 k,v = enum.next
   #=> [4321, [[4321, 62770, 2.0, 603.24], [4321, 105191, 2.0, 1900.8]]] 
 k #=> 4321 
 v #=> [[4321, 62770, 2.0, 603.24], [4321, 105191, 2.0, 1900.8]] 
 [k, v.size==1 ? v.first : v]
   #=> [4321, [[4321, 62770, 2.0, 603.24], [4321, 105191, 2.0, 1900.8]]] 

 k,v = enum.next
   #=> [1234, [[1234, 62770, 2.0, 603.24]]] 
 k #=> 1234 
 v #=> [[1234, 62770, 2.0, 603.24]] 
 [k, v.size==1 ? v.first : v]
   #=> [1234, [1234, 62770, 2.0, 603.24]] 

 k,v = enum.next
   #=> StopIteration: iteration reached an end

步骤:

localH2O

答案 2 :(得分:0)

你的问题不是很清楚。这是你想要的吗?

arrays = [ [ 8765, 105191, 2.0, 1582.1  ],
           [ 4321,  62770, 2.0,  603.24 ], 
           [ 4321, 105191, 2.0, 1900.8  ],
           [ 1234,  62770, 2.0,  603.24 ] ]

p arrays.group_by(&:shift)
# => { 8765 => [ [ 105191, 2.0, 1582.1  ] ],
#      4321 => [ [  62770, 2.0,  603.24 ],
#                [ 105191, 2.0, 1900.8  ] ],
#      1234 => [ [  62770, 2.0,  603.24 ] ]
#    }

注意:以上内容将修改原始数组。如果这是一个问题,请先dup

arrays.map(&:dup).group_by(&:shift)

或者这个怎​​么样?

keys = %w[ sales_user user_id month amount ]

p arrays.map {|values| keys.zip(values).to_h }
    .group_by {|hsh| hsh.delete("sales_user") }
# => { 8765 => [ { "user_id" => 105191, "month" => 2.0, "amount" => 1582.1  } ],
#      4321 => [ { "user_id" =>  62770, "month" => 2.0, "amount" =>  603.24 },
#                { "user_id" => 105191, "month" => 2.0, "amount" => 1900.8  } ],
#      1234 => [ { "user_id" =>  62770, "month" => 2.0, "amount" =>. 603.24 } ]
#    }