2017-01-14 55 views
0

我有一个CSV文件,我需要读取并提取在特定范围内具有“created_at”的所有行。 CSV本身在Excel中大约有5000行。如何从CSV文件解析哈希哈希

这是我如何从文件中提取的信息:

CSV.foreach("sample_data.csv", :headers => true, :header_converters => :symbol, :converters => :all) do |row| 
    data[row.fields[0]] = Hash[row.headers[1..-1].zip(row.fields[1..-1])] 
end 

下面是使用CSV.foreach后创建的最末尾的散列:

2760=>{:created_at=>1483189568, :readable_date=>"12/31/2016", :first_name=>"Louise", :last_name=>"Garza", :email=>"[email protected]", :gender=>"Female", :company=>"Cogilith", :currency=>"EUR", :word=>"orchestration", :drug_brand=>"EPIVIR", :drug_name=>"lamivudine", :drug_company=>"State of Florida DOH Central Pharmacy", :pill_color=>"Maroon", :frequency=>"Yearly", :token=>"_", :keywords=>"in faucibus", :bitcoin_address=>"19jTjXLPQUL1nEmHrpqeqM1FdtDFZmUZ2E"}} 

当我运行data[2759].first我得到:

created_at 
1309380645 

我需要拉每一个散列created_at介于range = 1403321503..1406082945之间。我尝试了使用eachcollectdata散列的二十种不同方法,但都没有成功。我最后一次尝试打印出每个原始散列的空{}

我想,没有成功测试:

data.each do |hash| 
    if hash.first.to_s.to_i > 1403321503 && hash.first.to_s.to_i < 1406082945 
    puts hash 
    end 
end 

我不知道如何隔离的key:created_at值,然后看它是否在范围内。我也试过做hash.first.to_s.to_i =/==的范围。

我能够通过使用data[1].first.last得到:created_at的值,但是当我尝试在方法中使用它时,它会出错。

这里是原来的CSV链接:goo.gl/NOjAPo

这不是我的工作电脑上,所以我不能做它的引擎收录。

+0

从描述中无法判断发生了什么。您需要提供几行数据,可生成错误答案的_runnable_代码以及相应的正确答案。例如。 “数据”是散列还是数组并不清楚。你为什么不直接用符号索引散列,'hash [:created_at]'? – Gene

+0

提示:'(x..y).include?(z)'是检查给定范围内是否有东西的更简洁的方法。你在这里有更多的详细信息,需要大量的冗余方法调用。 – tadman

+0

在做Ruby时要记住的另一件事是尝试将问题分解为一系列链接但简单的操作。例如,“拒绝”你不想要的行,或者“选择”你所做的行,然后把它们放进去。 – tadman

回答

0

我只会在data散列中存储行范围内的行。国际海事组织执行更好的,因为它需要更少的内存比读取所有数据到data并在第二步中删除不需要的条目。

DATE_RANGE = (1403321503..1406082945) 

CSV.foreach("sample_data.csv", 
      :headers => true, 
      :header_converters => :symbol, 
      :converters => :all) do |row| 
    attrs = Hash[row.headers[1..-1].zip(row.fields[1..-1])] 
    data[row.fields[0]] = attrs if DATE_RANGE.cover?(attrs[:created_at]) 
end 

这可能是有意义通过检查DATE_RANGE.cover?对列数实际创建哈希之前检查的条件(在row.fields[1]created_at?)。

+0

请尊重体力活动并不是很宽的屏幕,并在答案中划出长长的一行。 – mudasobwa

+0

@mudasobwa我以为是好的,因为那条线是由OP提供的,并没有引起问题,并且在我的答案中没有改变。对于那个很抱歉。我用改进的线条长度更新了我的答案。 – spickermann

+0

谢谢!这是有道理的提醒那些谁只听:) – mudasobwa

0

使用Enumerable#select

hash.select do |_, v| 
    (1403321503..1406082945) === v[:created_at] 
end 

在这里我们也使用Range#===又称病例等于或三相等,以检查值的范围之内。

+0

当我尝试做这样的事情之前,它错误了。尽管如此,我确实已经与.to_s.to_i一起工作。 我应该在括号内还是外面添加.to_s.to_i? v [:created_at] .to_s.to_i 或 v [:created_at.to_s.to_i] –

+0

将符号转换为字符串,然后转换为整数意义不大。目前还不清楚,为什么你要这样做,但如果你愿意,可以转换整个'v [:created_at]'值。 – mudasobwa

+0

当我试图使用=或==与范围我得到的错误,我是比较类型,单独尝试.to_i,但没有工作,所以我没有 - >字符串 - >整数,以确保它是一个整数。 –