我是Ruby新手(以及一般的编程新手)。我有一个哈希,它使用来自外部文件的数据,我试图获得大于1500的值的总数。
这是我的代码实际上,我需要条目的数量和超过1500的购买订单的总价值。外部文件只是一列订单号和一列价格。我相信有一个非常简单的解决方案,但就像我说的,我是一个初学者,不能想出它。任何帮助都会很感激。谢谢。
编辑:这是我的代码。就是最后那个while循环导致了所有的问题。我知道那不是正确的做法,但我就是不知道该怎么办。myhash={}
file=File.open("Purchase Orders.csv", "r")
while !file.eof
line=file.readline
key,value=line.chomp.split(",")
myhash[key]=value
end
total=0
entries=myhash.length
newtotal=0
myhash.each { |key,value|
total+=value.to_f
}
puts total
puts entries
while value.to_f>1500
myhash.each {|key,value| newtotal+=value.to_f}
end
puts newtotal
我将以ruby惯用的方式重写代码,希望您能检查它并从中找到一些提示。
prices = File.readlines("Purchase Orders.csv").map do |line|
line.chomp.split(",").last.to_f
end # array of prices
total = prices.inject(:+) # sum values
pricy = prices.select { |v| v > 1500 }
pricy_sum = pricy.inject(:+) # sum expensives
pricy_count = pricy.length # expensives’ size
puts "Total sum is: #{total}"
puts "Total expensives is: #{pricy}"
看起来你把循环颠倒了。此外,对于多行代码块,通常首选使用do和end,而不是大括号,而大括号通常用于单行代码块(如@mudasobwa所述)。查看ruby风格指南,了解更多的风格指针。
myhash.each do |key,value|
newtotal+=value.to_f if value.to_f > 1500
end
puts newtotal
代码
def nbr_and_tot(fname)
File.foreach(fname).with_object({ nbr_over: 0, tot_over: 0 }) do |line, h|
n = line[/d+/].to_i
if n > 1500
h[:nbr_over] += 1
h[:tot_over] += n
end
end
end
首先创建一个文件"temp":
str =<<-END
:cat, 1501
:dog, 1500
:pig, 2000
END
File.write("temp", str)
#=> 33
确认文件是否正确:
puts File.read("temp")
打印
:cat, 1501
:dog, 1500
:pig, 2000
现在执行方法。
nbr_and_tot "temp"
#=> {:nbr_over=>2, :tot_over=>3501}
首先回顾一下IO::foreach,它逐行读取文件1并返回一个链接到with_object
、enumerator #with_object和String#[]的枚举数。
例如
fname = "temp"
e0 = File.foreach(fname)
#=> #<Enumerator: File:foreach("temp")>
通过将枚举器转换为数组,我们可以看到该枚举器将生成的值(并传递给each_object
):
e0.to_a
#=> [":cat, 1501n", ":dog, 1500n", ":pig, 2000n"]
在继续,
e1 = e0.with_object({ nbr_over: 0, tot_over: 0 })
#=> #<Enumerator: #<Enumerator: 2.3.0 :171 >
e1.to_a
#=> [[":cat, 1501n", {:nbr_over=>0, :tot_over=>0}],
# [":dog, 1500n", {:nbr_over=>0, :tot_over=>0}],
# [":pig, 2000n", {:nbr_over=>0, :tot_over=>0}]]
e1
生成的第一个元素被传递给块,块变量被赋值,使用并行赋值:
line, h = e1.next
#=> [":cat, 1501n", {:nbr_over=>0, :tot_over=>0}]
line
#=> ":cat, 1501n"
h #=> {:nbr_over=>0, :tot_over=>0}
和n
计算:
s = line[/d+/]
#=> "1501"
n = s.to_i
#=> 1501
作为n > 1500 #=> true
,我们执行以下操作:
h[:nbr_over] += 1
#=> 1
h[:tot_over] += n
#=> 1501
现在h #=> {:nbr_over=>1, :tot_over=>1501}
现在e1
的第二个元素被传递到块中,执行以下步骤:
line, h = e1.next
#=> [":dog, 1500n", {:nbr_over=>1, :tot_over=>1501}]
line
#=> ":dog, 1500n"
h #=> {:nbr_over=>1, :tot_over=>1501}
n = line[/d+/].to_i
#=> 1500
作为n > 1500 #=> fasle
,这一行被跳过。e1
生成的最后一个元素的处理与第一个元素的处理类似。
1 File
是IO
(File < IO #=> true
)的子类,因此IO
类方法如foreach
经常在File类(File.foreach...
)上调用。