Ruby - 无法总结哈希值

时间:2016-11-16 08:08:58

标签: ruby

我是Ruby的新手(以及一般的编程)。我有一个使用外部文件数据的哈希,我试图获得大于1500的值的总数。

Here's my code实际上,我需要超过1500的订单数量和采购订单总价值。外部文件只是一列订单号和一列价格。我确定有一个非常简单的解决方案,但就像我说我是一个初学者并且无法弄明白。任何帮助,将不胜感激。感谢。

编辑:这是我的代码。它只是最后一次循环导致所有问题。我知道这不是正确的方法,但我无法弄清楚该怎么做。

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

3 个答案:

答案 0 :(得分:3)

我会用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}"

答案 1 :(得分:1)

看起来你已经扭转了你的循环。此外,对于多行代码块,使用do和end通常优于花括号,而花括号通常用于单行块(如@mudasobwa所述)。查看ruby style guide以获取更多样式指针。

myhash.each do |key,value| 
    newtotal+=value.to_f if value.to_f > 1500
end
puts newtotal

答案 2 :(得分:1)

<强>代码

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

示例

首先让我们创建一个文件&#34; temp&#34;:

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的{​​{3}}枚举数}和Enumerator#with_object

例如,

fname = "temp"
e0 = File.foreach(fname)
  #=> #<Enumerator: File:foreach("temp")> 

我们可以通过将此枚举器转换为数组来查看此枚举器生成的值(并传递给each_object):

e0.to_a
  #=> [":cat, 1501\n", ":dog, 1500\n", ":pig, 2000\n"] 

继续,

e1 = e0.with_object({ nbr_over: 0, tot_over: 0 })
  #=> #<Enumerator: #<Enumerator: 2.3.0 :171 >
e1.to_a
  #=> [[":cat, 1501\n", {:nbr_over=>0, :tot_over=>0}],
  #    [":dog, 1500\n", {:nbr_over=>0, :tot_over=>0}],
  #    [":pig, 2000\n", {:nbr_over=>0, :tot_over=>0}]] 

e1生成的第一个元素将传递给块,并使用并行分配为块变量赋值:

line, h = e1.next
  #=> [":cat, 1501\n", {:nbr_over=>0, :tot_over=>0}] 
line
  #=> ":cat, 1501\n" 
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, 1500\n", {:nbr_over=>1, :tot_over=>1501}] 
line
  #=> ":dog, 1500\n" 
h #=> {:nbr_over=>1, :tot_over=>1501} 
n = line[/\d+/].to_i
  #=> 1500

作为n > 1500 #=> fasle,跳过此行。 e1生成的最后一个元素的处理类似于第一个元素的处理。

1 FileIOFile < IO #=> true)的子类,因此IO类方法(例如foreach)通常会在文件上调用class(File.foreach...