红宝石自动复活
我一直在尝试在 ruby 中使用 autovivification 对此进行简单的记录合并:
2009-08-21|09:30:01|A1|EGLE|Eagle Bulk Shpg|BUY|6000|5.03
2009-08-21|09:30:35|A2|JOYG|Joy Global Inc|BUY|4000|39.76
2009-08-21|09:30:35|A2|LEAP|Leap Wireless|BUY|2100|16.36
2009-08-21|09:30:36|A1|AINV|Apollo Inv Cp|BUY|2300|9.15
2009-08-21|09:30:36|A1|CTAS|Cintas Corp|SELL|9800|27.83
2009-08-21|09:30:38|A1|KRE|SPDR KBW Regional Banking ETF|BUY|9200|21.70
2009-08-21|09:30:39|A1|APA|APACHE CORPORATION|BUY|5700|87.18
2009-08-21|09:30:40|A1|FITB|Fifth Third Bancorp|BUY|9900|10.86
2009-08-21|09:30:40|A1|ICO|INTERNATIONAL COAL GROUP, INC.|SELL|7100|3.45
2009-08-21|09:30:41|A1|NLY|ANNALY CAPITAL MANAGEMENT. INC.|BUY|3000|17.31
2009-08-21|09:30:42|A2|GAZ|iPath Dow Jones - AIG Natural Gas Total Return Sub-Index ETN|SELL|6600|14.09
2009-08-21|09:30:44|A2|CVBF|Cvb Finl|BUY|1100|7.64
2009-08-21|09:30:44|A2|JCP|PENNEY COMPANY, INC.|BUY|300|31.05
2009-08-21|09:30:36|A1|AINV|Apollo Inv Cp|BUY|4500|9.15
例如,我希望 A1 AINV BUY 9.15 的记录总数为 6800。这是使用 autovivification 的完美问题。所以这是我的代码:
#!/usr/bin/ruby
require 'facets'
h = Hash.autonew
File.open('trades_long.dat','r').each do |line|
@date,@time,@account,@ticker,@desc,@type,amount,@price = line.chomp.split('|')
if @account != "account"
puts "#{amount}"
h[@account][@ticker][@type][@price] += amount
end
#puts sum.to_s
end
问题是无论我如何尝试总结 h[@account][@ticker][@type][@price] 中的值,它都会给我这个错误:
6000
/usr/local/lib/ruby/gems/1.9.1/gems/facets-2.7.0/lib/core/facets/hash/op_add.rb:8:in `merge': can't convert String into Hash (TypeError)
from /usr/local/lib/ruby/gems/1.9.1/gems/facets-2.7.0/lib/core/facets/hash/op_add.rb:8:in `+'
from ./trades_consolidaton.rb:13
from ./trades_consolidaton.rb:8:in `each'
from ./trades_consolidaton.rb:8
我尝试使用不同的“autovivification” ”没有结果的方法。这在 Perl 中不会发生!自动激活会知道你想做什么。 ruby好像没有这个功能。
所以我的问题实际上是,如何在 ruby 中执行简单的记录“合并”。具体来说,我如何获得类似以下内容的总计:
h[@account][@ticker][@type][@price]
非常感谢您的帮助!
只是为了澄清格伦的解决方案。这将是完美的,除了它给出(进行一些修改以使用 ruby 1.9 中的标准 CSV 库:
CSV.foreach("trades_long.dat", :col_sep => "|") do |row|
date,time,account,ticker,desc,type,amount,price = *row
records[[account,ticker,type,price]] += amount
end
给出以下错误:
TypeError: String can't be coerced into Fixnum
from (irb):64:in `+'
from (irb):64:in `block in irb_binding'
from /usr/local/lib/ruby/1.9.1/csv.rb:1761:in `each'
from /usr/local/lib/ruby/1.9.1/csv.rb:1197:in `block in foreach'
from /usr/local/lib/ruby/1.9.1/csv.rb:1335:in `open'
from /usr/local/lib/ruby/1.9.1/csv.rb:1196:in `foreach'
from (irb):62
from /usr/local/bin/irb:12:in `<main>'
I've been trying to use autovivification in ruby to do simple record consolidation on this:
2009-08-21|09:30:01|A1|EGLE|Eagle Bulk Shpg|BUY|6000|5.03
2009-08-21|09:30:35|A2|JOYG|Joy Global Inc|BUY|4000|39.76
2009-08-21|09:30:35|A2|LEAP|Leap Wireless|BUY|2100|16.36
2009-08-21|09:30:36|A1|AINV|Apollo Inv Cp|BUY|2300|9.15
2009-08-21|09:30:36|A1|CTAS|Cintas Corp|SELL|9800|27.83
2009-08-21|09:30:38|A1|KRE|SPDR KBW Regional Banking ETF|BUY|9200|21.70
2009-08-21|09:30:39|A1|APA|APACHE CORPORATION|BUY|5700|87.18
2009-08-21|09:30:40|A1|FITB|Fifth Third Bancorp|BUY|9900|10.86
2009-08-21|09:30:40|A1|ICO|INTERNATIONAL COAL GROUP, INC.|SELL|7100|3.45
2009-08-21|09:30:41|A1|NLY|ANNALY CAPITAL MANAGEMENT. INC.|BUY|3000|17.31
2009-08-21|09:30:42|A2|GAZ|iPath Dow Jones - AIG Natural Gas Total Return Sub-Index ETN|SELL|6600|14.09
2009-08-21|09:30:44|A2|CVBF|Cvb Finl|BUY|1100|7.64
2009-08-21|09:30:44|A2|JCP|PENNEY COMPANY, INC.|BUY|300|31.05
2009-08-21|09:30:36|A1|AINV|Apollo Inv Cp|BUY|4500|9.15
so for example I want the record for A1 AINV BUY 9.15 to have a total of 6800. This is a perfect problem to use autovivification on. So heres my code:
#!/usr/bin/ruby
require 'facets'
h = Hash.autonew
File.open('trades_long.dat','r').each do |line|
@date,@time,@account,@ticker,@desc,@type,amount,@price = line.chomp.split('|')
if @account != "account"
puts "#{amount}"
h[@account][@ticker][@type][@price] += amount
end
#puts sum.to_s
end
The problem is no matter how I try to sum up the value in h[@account][@ticker][@type][@price] it gives me this error:
6000
/usr/local/lib/ruby/gems/1.9.1/gems/facets-2.7.0/lib/core/facets/hash/op_add.rb:8:in `merge': can't convert String into Hash (TypeError)
from /usr/local/lib/ruby/gems/1.9.1/gems/facets-2.7.0/lib/core/facets/hash/op_add.rb:8:in `+'
from ./trades_consolidaton.rb:13
from ./trades_consolidaton.rb:8:in `each'
from ./trades_consolidaton.rb:8
I've tried using different "autovivification" methods with no result. This wouldn't happen in perl! The autofvivification would know what you are trying to do. ruby doesn't seem to have this feature.
So my question really is, how do I perform simply "consolidation" of records in ruby. Specifically, how do I get the total for something like:
h[@account][@ticker][@type][@price]
Many thanks for your help!!
Just to clarify on glenn's solution. That would be perfect except it gives (with a few modifications to use the standard CSV library in ruby 1.9:
CSV.foreach("trades_long.dat", :col_sep => "|") do |row|
date,time,account,ticker,desc,type,amount,price = *row
records[[account,ticker,type,price]] += amount
end
gives the following error:
TypeError: String can't be coerced into Fixnum
from (irb):64:in `+'
from (irb):64:in `block in irb_binding'
from /usr/local/lib/ruby/1.9.1/csv.rb:1761:in `each'
from /usr/local/lib/ruby/1.9.1/csv.rb:1197:in `block in foreach'
from /usr/local/lib/ruby/1.9.1/csv.rb:1335:in `open'
from /usr/local/lib/ruby/1.9.1/csv.rb:1196:in `foreach'
from (irb):62
from /usr/local/bin/irb:12:in `<main>'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我同意乔纳斯的观点,你(和山姆)让事情变得比需要的更复杂,但我认为即使是他的版本也太复杂了。我只是这样做:
现在你有了一个哈希值,其中包含帐户、股票代码、类型和价格的每个独特组合的总金额。
I agree with Jonas that you (and Sam) are making this more complicated than it needs to be, but I think even his version is too complicated. I'd just do this:
Now you have a hash with total amounts for each unique combination of account, ticker, type and price.
如果您想要一个以这种方式工作的哈希生成器,您将必须重新定义
+
语义。例如,这工作得很好:
本质上,您正在尝试将
+
运算符应用于哈希。但是在facets{中,
如果您想在这种情况下重新定义散列的+语义,您可以执行以下操作:
将此片段放在原始示例之前,一切都应该很好。请记住,您正在更改 + 的定义行为(注意 + 未在其与构面拉入的哈希上定义)
If you want a hash builder that works that way, you are going to have to redefine the
+
semantics.For example, this works fine:
Essentially you are trying to apply the
+
operator to a Hash.However in facets{
If you want to redefine the + semantics for your hash in this occasion you can do:
Place this snippet before your original sample and all should be well. Keep in mind that you are changing the defined behavior for + (note + is not defined on Hash its pulled in with facets)
看来你让事情变得比实际情况更复杂了。我会使用 FasterCSV gem 和 Enumerable#inject ,如下所示:
It looks like you are making it more complicated than it has to be. I would use the FasterCSV gem and Enumerable#inject something like this:
对于其他在这里找到路的人来说,现在还有另一个选择:
这将生成一个可导航的结构。 (如前所述,使用
[@account, @ticker, @type, @price] 数组进行传统键控可能更适合此特定应用程序)。
XKeys
在写入时自动激活,而不是在读取时自动激活,因此查询不存在元素的结构不会更改结构。For others that find their way here, there is now also another option:
This will generate a navigable structure. (Traditional keying with arrays of
[@account, @ticker, @type, @price]
as suggested earlier may be better this particular application).XKeys
auto-vivifies on write rather than read, so querying the structure about elements that don't exist won't change the structure.