我有一个由Postgres支持的Ruby项目。我的表有一个名为first_ship_date
的日期字段,以及一个Rails枚举的传递状态。
我需要创建一个类似于以下内容的哈希或数组:
[ { week: 2016-01-04,
0: 15,
1: 30,
2: 8
},
{ week: 2016-01-11,
0: 8,
1: 45,
2: 37
}
]
一旦完成,我将在Google Chart中显示结果。
这是我到目前为止所做的:
SalesOrder.order("date_trunc('week', first_ship_date) ASC")
.where("delivery_status is not null")
.where("date(first_ship_date) >= ? AND date(first_ship_date) <=?", Date.new(2016,1,1), Date.new(2016,3,31))
.pluck("date_trunc('week', first_ship_date)", :delivery_status)
返回一个值类似于:
的数组[ [2016-01-04 00:00:00 UTC, 0],
[2016-01-04 00:00:00 UTC, 2],
[2016-01-04 00:00:00 UTC, 2],
[2016-01-04 00:00:00 UTC, 2],
[2016-01-04 00:00:00 UTC, 2] ]
将此原始数据转换为上面的哈希/数组的最佳和最有效的方法是什么,请记住枚举的值始终不可见?这意味着,几周之内我们没有所有的delivery_status值。
答案 0 :(得分:0)
<强> ANSWER 强>
使用Enumerable#inject
:http://ruby-doc.org/core-2.3.1/Enumerable.html#method-i-inject
一衬垫:
your_array_or_arobject.inject({}) {|h,y| h[week = y[0].to_date.to_s] ||= []; h[week] << y[1]; h}.inject({}) {|h,(k,v)| h[k] = {week: k}.merge(v.each_with_index.inject({}) {|h,(k,i)| h[i] = k; h}); h}.values
#=> [{:week=>"2016-01-04", 0=>15, 1=>30, 2=>8}, {:week=>"2016-01-11", 0=>8, 1=>45, 2=>37}]
多:
hash = your_array_or_arobject.inject({}) do |h,y|
h[week = y[0].to_date.to_s] ||= []
h[week] << y[1]
h
end
hash2 = hash.inject({}) do |h,(k,v)|
h[k] = {week: k}.merge(
v.each_with_index.inject({}) do |h2,(k,i)|
h2[i] = k
h2
end
)
h
end
hash2.values
#=> [{:week=>"2016-01-04", 0=>15, 1=>30, 2=>8}, {:week=>"2016-01-11", 0=>8, 1=>45, 2=>37}]
证明
通过控制台:
irb(main):159:0> x = [ irb(main):160:1* ["2016-01-04 00:00:00 UTC", 15], irb(main):161:1* ["2016-01-04 00:00:00 UTC", 30], irb(main):162:1* ["2016-01-04 00:00:00 UTC", 8], irb(main):163:1* irb(main):164:1* ["2016-01-11 00:00:00 UTC", 8], irb(main):165:1* ["2016-01-11 00:00:00 UTC", 45], irb(main):166:1* ["2016-01-11 00:00:00 UTC", 37] irb(main):167:1> ] => [["2016-01-04 00:00:00 UTC", 15], ["2016-01-04 00:00:00 UTC", 30], ["2016-01-04 00:00:00 UTC", 8], ["2016-01-11 00:00:00 UTC", 8], ["2016-01-11 00:00:00 UTC", 45], ["2016-01-11 00:00:00 UTC", 37]] irb(main):168:0> x.map! {|y| [DateTime.parse(y[0]), y[1]]} => [[Mon, 04 Jan 2016 00:00:00 +0000, 15], [Mon, 04 Jan 2016 00:00:00 +0000, 30], [Mon, 04 Jan 2016 00:00:00 +0000, 8], [Mon, 11 Jan 2016 00:00:00 +0000, 8], [Mon, 11 Jan 2016 00:00:00 +0000, 45], [Mon, 11 Jan 2016 00:00:00 +0000, 37]] irb(main):169:0> hash = x.inject({}) {|h,y| h[week = y[0].to_date.to_s] ||= []; h[week] {"2016-01-04"=>[15, 30, 8], "2016-01-11"=>[8, 45, 37]} irb(main):170:0> hash.inject({}) {|h,(k,v)| h[k] = {week: k}.merge(v.each_with_index.inject({}) {|h,(k,i)| h[i] = k; h}); h}.values => [{:week=>"2016-01-04", 0=>15, 1=>30, 2=>8}, {:week=>"2016-01-11", 0=>8, 1=>45, 2=>37}]
<强>更新强>
重构每个值的出现次数。
一衬垫:
your_array_or_arobject.inject({}) {|h,y| h[week = y[0].to_date.to_s] ||= []; h[week] << y[1]; h}.inject({}) {|h1,(k,v)| h1[k] = {week: k}.merge(v.inject({}) {|h2,k| h2[k] ||= 0; h2[k] += 1; h2}); h1}.values
多:
hash = your_array_or_arobject.inject({}) do |h,y|
h[week = y[0].to_date.to_s] ||= []
h[week] << y[1]
h
end
hash2 = hash.inject({}) do |h1,(k,v)|
h1[k] = {week: k}.merge(
v.inject({}) do |h2,k|
h2[k] ||= 0
h2[k] += 1
h2
end
)
h1
end
hash2.values
<强> PROOF 强>
通过控制台:
irb(main):001:0> require 'date'
=> true
irb(main):002:0> x = [
irb(main):003:1* ['2016-01-04 00:00:00 UTC', 0],
irb(main):004:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):005:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):006:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):007:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):008:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):009:1* ['2016-01-04 00:00:00 UTC', 0],
irb(main):010:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):011:1* ['2016-01-04 00:00:00 UTC', 0],
irb(main):012:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):013:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):014:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):015:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):016:1* ['2016-01-04 00:00:00 UTC', 2],
irb(main):017:1* ['2016-01-04 00:00:00 UTC', 2]
irb(main):018:1> ]
=> [["2016-01-04 00:00:00 UTC", 0], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 0], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 0], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2], ["2016-01-04 00:00:00 UTC", 2]]
irb(main):019:0> x.map! {|y| [DateTime.parse(y[0]), y[1]]}
=> [[#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 0], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 0], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 0], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2], [#<DateTime: 2016-01-04T00:00:00+00:00 ((2457392j,0s,0n),+0s,2299161j)>, 2]]
irb(main):020:0> x.inject({}) {|h,y| h[week = y[0].to_date.to_s] ||= []; h[week] << y[1]; h}.inject({}) {|h1,(k,v)| h1[k] = {week: k}.merge(v.inject({}) {|h2,k| h2[k] ||= 0; h2[k] += 1; h2}); h1}.values
=> [{:week=>"2016-01-04", 0=>3, 2=>12}]