我需要构建一个对象数组,以在图表上显示数据,该图表显示过去7天的数据。有时,数据库中将缺少7天记录中的某些记录,因此我需要显示记录并将值标记为0以在数组中包含7个对象。
现在我有
[
{
"date": "2016-05-14",
"amount": 6000
},
{
"date": "2016-05-12",
"amount": 12000
}
]
我想要的是
[
{
"date": "2016-05-14",
"amount": 6000
},
{
"date": "2016-05-13",
"amount": 0
},
{
"date": "2016-05-12",
"amount": 12000
},
{
"date": "2016-05-11",
"amount": 0
},
{
"date": "2016-05-10",
"amount": 0
},
{
"date": "2016-05-09",
"amount": 0
},
{
"date": "2016-05-09",
"amount": 0
}
]
答案 0 :(得分:6)
ts = JSON.parse '[
{
"date": "2016-05-14",
"amount": 6000
},
{
"date": "2016-05-12",
"amount": 12000
}]' # support ruby < 2.2
((Date.today-6..Date.today).map do |d|
[d.iso8601, {'amount' => 0, 'date' => d.iso8601 }]
end.to_h.merge ts.group_by { |e| e['date'] }).values.flatten
这里我们首先构建映射到零值的请求天数的哈希值,然后将其与现有值的哈希值合并。后者优先:
[Date.today].map do |d|
[d.iso8601, {'amount' => 0, 'date' => d.iso8601 }]
end.to_h
#⇒ { '2016-05-16' => {'amount' => 0, 'date' => '2016-05-16' } }
(在真正的哈希中有七个项目。)
Enumerable#group_by
产生相同的结构:
[ {'amount' => 42, 'date' => Date.today } ].group_by { |e| e['date'] }
#⇒ { '2016-05-16' => [{'amount' => 42, 'date' => '2016-05-16' }] }
作为最后一步,我们将后者合并到前者中,并通过获取结果的values
并将其展平来摆脱日期键。
使用Hash#default_proc
:
hsh = Hash.new do |h, k|
ts.detect do |e|
e['date'] == k.iso8601
end || { 'amount' => 0, 'date' => k.iso8601 }
end
(Date.today-6..Date.today).map { |d| hsh[d] }
答案 1 :(得分:2)
通过map reduce的功能方法可能是最简单和最有效的:
timeseries = [
{
"date": "2016-05-14",
"amount": 6000
},
{
"date": "2016-05-12",
"amount": 12000
}
]
last_7_days = 6.days.ago.to_date..Date.today
# Transform array of hashes into a single hash with each key as a Date object.
# Eg. { "2016-05-12" => 12000, "2016-05-14" => 6000 }
counts_each_day = timeseries.reduce(Hash.new(0)) do |acc, item|
acc.merge(Date.parse(item[:date]) => item[:amount])
end
# Merge the results with an empty count, if it doesn't exist in our transformed hash.
filled_timeseries = last_7_days.map do |day|
{ date: day.to_s, amount: counts_each_day[day] }
end
<强>结果强>
[
{ :date => "2016-05-10", :amount => 0 },
{ :date => "2016-05-11", :amount => 0 },
{ :date => "2016-05-12", :amount => 12000 },
{ :date => "2016-05-13", :amount => 0 },
{ :date => "2016-05-14", :amount => 6000 },
{ :date => "2016-05-15", :amount => 0 },
{ :date => "2016-05-16", :amount => 0 }
]
答案 2 :(得分:1)
我希望这会有所帮助。
data = [
{
"date": "2016-05-14",
"amount": 6000
},
{
"date": "2016-05-12",
"amount": 12000
}] # Given data
dates = data.map do |datum| datum[:date] end # Extract dates from data.
today = Date.today # Get today.
dates_list = 7.times.map do |index| (today + index).strftime("%F") end # Get 7days from today.
dates_list.each do |date|
next if dates.include? date # if data already includes the date, such as "2016-05-14", pass.
data << {"date": date, "amount": 0} # if data does not include the date, append it with amount 0.
end
答案 3 :(得分:1)
这将得到正确答案:
require 'date'
require 'pp'
data = [
{
"date": "2016-05-14",
"amount": 6000
},
{
"date": "2016-05-12",
"amount": 12000
}
]
pp data
today = DateTime.now
7.times do |day|
current_day = (DateTime.now - day).strftime("%F")
next if data.find_index {|hash| hash[:date] == current_day }
data.push({ "date": current_day, "amount": 0 })
end
pp data
这将产生以下输出:
[{:date=>"2016-05-14", :amount=>6000},
{:date=>"2016-05-12", :amount=>12000},
{:date=>"2016-05-15", :amount=>0},
{:date=>"2016-05-13", :amount=>0},
{:date=>"2016-05-11", :amount=>0},
{:date=>"2016-05-10", :amount=>0},
{:date=>"2016-05-09", :amount=>0}]
如果您希望按日期排序数组,可以使用:
data.sort {|a,b| a[:date] <=> b[:date] }.reverse
这将产生此输出:
[{:date=>"2016-05-15", :amount=>0},
{:date=>"2016-05-14", :amount=>6000},
{:date=>"2016-05-13", :amount=>0},
{:date=>"2016-05-12", :amount=>12000},
{:date=>"2016-05-11", :amount=>0},
{:date=>"2016-05-10", :amount=>0},
{:date=>"2016-05-09", :amount=>0}]
答案 4 :(得分:1)
这里我认为另一种方法相当清楚,并从数据而不是Date.today获取开始日期。它假定输入中没有无效日期,并且输入不为空。
请注意,通过指定class test24{
public static void main ( String [] args ) {
int[] arr = {6,3,9,0};
test24 test = new test24();
System.out.println(Arrays.deepToString(test.repmat(arr,2,1,2)));
}
public static int[][][] repmat (int[] array, int rows, int columns, int depth)
{
int arrayColumns = array.length;
int resultColumns = arrayColumns * columns;
int[][][] result = new int[rows][resultColumns][depth];
int z = 0;
for (int d = 0; d < depth; d++)
{
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < resultColumns; c++)
{
result[r][c][d] = array[z++];
if (z >= arrayColumns)
{
z = 0;
}
}
}
}
return result;
}
}
某些内容,您可以使用与"string":...
相同的内容,但需要采用更加混乱的方式。我想这是来自JSON数据,但它应该被解析为一个Ruby数组的哈希。我在我的代码中对此进行了更改。
string:...
顺便说一句,这可以在没有Rails的Ruby中运行。此外,代码发布在https://gist.github.com/keithrbennett/fd876aac938f1e5d6222896dbd30e8f2。