2017-01-30 31 views
1

所以基本上我试图通过Ruby在一个巨大的csv文件中查找一些信息(注意我不想要excel解决方案),我已将unix时间戳转换为适当的时间对象,并对它们进行排序并通过#select过滤。我试图在给定的特定时间范围内找到有关purchase_amt的信息(我用start_date,end_date表示)。pure ruby​​:通过#select过滤csv日期,但现在想要基于这些日期范围获得另一列

目前我只有一个通过巨大的csv过滤的时间数组,但我怎样才能使用我的代码来获取csv中给出的purchase_amt?

Unix_time purchase_amt 
1352948920 12.40 

require 'csv' 
require 'date' 

start_date = DateTime.rfc3339('2014-06-22T00:00:00Z').to_time.to_i 
end_date = DateTime.rfc3339('2014-07-22T00:00:00Z').to_time.to_i 

csv = CSV.parse('sample_data.csv', headers: true, encoding: 'ISO-8859-1') 

csv.each do |row| 
    if (row['created_at'] >= start_date && row['created_at'] <= end_date) 
     final_arry<< row 
    end 
end 

puts csv 
+0

我想我会通过CSV [“purchase_amt”]这是直截了当访问purchase_amt,但我想知道我怎么再与处理这个庞大的阵列并应用我之前做过的筛选工作... – cristodagama

+0

一个解决方案可能是在第一次迭代时在csv中修改列值(Unix_time),因此每列都有根据您的需求的日期,然后在第二次迭代你可以检查它是否属于start_date或end_date..if是,然后获取行['purchase_amt']。 – Abhinay

+0

你能澄清吗?也许给我举个例子吧? – cristodagama

回答

3

如果你有一个巨大的CSV,你应该使用CSV.foreach。 它一个接一个地解析行而不将整个文件加载到内存中。

Range#cover?还帮助:

返回true如果obj是开始和范围的结束之间。

如果可以的话,还应该在块内进行所有计算,而不返回一个也可能变得很大的新数组。看来你确实需要一个巨大的数组,虽然,所以这里有云:

require 'csv' 

amounts = [] 

start_date = Time.new(2012, 1, 22) 
end_date = Time.new(2014, 7, 22) 

search_range = (start_date.to_i..end_date.to_i) 

CSV.foreach('data.csv', headers: true, col_sep: "\s", skip_blanks: true) do |row| 
    next unless search_range.cover?(row['Unix_time'].to_i) 
    amounts << row['purchase_amt'].to_f 
end 

p amounts 
+0

这与我想要的@EricDuminil非常接近,但不是总计总和,我只是想要在搜索范围之间出售的每个price_amts的列表。那有意义吗? – cristodagama

+0

所以基本上,而不是总有我的Ln,我希望我可以提取数组中的每个个体 – cristodagama

1

如果我没有错,你想提取落在start_date..end_date范围下的记录。 现在比较好的解决办法是只是你的起始日期日期和结束日期转换为unix时间戳,如:

require 'date' 

DateTime.rfc3339('2015-05-27T07:39:59Z') 
#=> #<DateTime: 2015-05-27T07:39:59+00:00 ((2457170j,27599s,0n),+0s,2299161j)> 

DateTime.rfc3339('2015-05-27T07:39:59Z').to_time 
#=> 2015-05-27 09:39:59 +0200 

DateTime.rfc3339('2015-05-27T07:39:59Z').to_time.to_i 
#=> 1432712399 

这里提到:https://stackoverflow.com/a/30480999/2545197

现在你应该可以通过像CSV运行:

csv = CSV.parse('sample_data.csv', :headers => true, :encoding => 'ISO-8859-1') 
csv.each do |row| 
    # apply your conditions here 
    # something like... 
    if row['date'] >=start_date && row['date']<=end_date 
    # append it to some array 
    # ary << row 
    end 
end 

让我知道这对你的作品

+0

,以便不输出任何东西...虐待更新我的代码上面,告诉你怎么回事 – cristodagama

+0

我没有得到任何输出....请参阅更新 – cristodagama

+0

记得我想购买最终基于关闭日期选择的条件 – cristodagama