Ruby -不能对哈希值求和



我是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 FileIO (File < IO #=> true)的子类,因此IO类方法如foreach经常在File类(File.foreach...)上调用。

最新更新