更新计数器时通过哈希迭代

时间:2014-03-26 03:20:50

标签: ruby

我有一个哈希:

students = {
  class1: 11,
  class2: 24,
  class3: 38,
  class4: 62
}

我希望有四行输出:

1) 11  
2) 35 #11 + 24  
3) 73 #35 + 38  
4) 135 #73 + 62

它遍历每个元素,并向计数器添加一个值,随着时间的推移打印每个迭代。我需要这样的东西:

students.each do |key, value|
  value + counter = total
  puts total
end  

但我不知道该怎么做。请指教。

3 个答案:

答案 0 :(得分:4)

有很多方法可以做到这一点,但我会建议一种方法来教你一些关于Ruby的不同内容。这也是一种非常类似于Ruby的方法来解决这个问题。

<强>代码

students = {
class1: 11,
class2: 24,
class3: 38,
class4: 62 }

students.reduce(0) do |tot, (k,v)|
  tot += v
  puts k[/\d+/] + ") #{tot}"
  tot
end
1) 11
2) 35
3) 73
4) 135

<强>解释

我使用了Enumerable#reduce(又名inject),因为该方法可以方便地汇总数字集合,使用一个变量(此处为tot)来维持其中的运行总数块。这正是你所需要的。

除此之外:您将学习很多阅读Ruby方法的文档。方法的引用方式如下:SomeClass#methodSomeModule#method。这里,reduce是模块Enumerable的实例方法。 students是类Hash的一个实例,但该类“混合”(包括)模块Enumerable的实例方法。

对象totFixnum,它被初始化为reduce的参数,此处为零。 (如果没有给出初始值,则student - 11 - 的初始值将分配给tot)。每次执行块中的代码时,块末尾的值都会返回到枚举器(这就是tot存在的原因)。在枚举了接收器students的所有元素之后,tot返回reduce的值(尽管您不会使用它)。

第一次调用块时,块变量如下:

tot => 0
k   => :class1
v   => 11

打印

1) 11

我认为您希望标签1)成为:class1的右端。要从符号1中精确k => :class1,您可以使用方法Symbol#[]和正则表达式/\d+/,后者提取一个或多个数字0-9的字符串(尽可能多因为有)。

在阅读方法Symbol#[]的文档时,您会看到它将符号:class1转换为字符串"class1",然后在该字符串上调用方法String[]

自Ruby 1.9+以来,许多人更喜欢使用Enumerable#each_with_object而不是reduce。该方法将使用如下:

students.each_with_object(0) do |(k,v),tot|
  tot += v
  puts k[/\d+/] + ") #{tot}"
end

请注意,使用此方法时,不必将对象(tot)的值返回到枚举器,并且tot位于块变量列表的末尾,而它是reduce的开头。

答案 1 :(得分:0)

你实际上相当接近。您需要在块之外定义total变量,只需使用

为其分配0
total=0

这将使其贯穿所有迭代。

然后你需要做一些小改动
students.each do |key, value|
  total=total+value
  puts total
end

它会做你想要的。

切换value + counter = total的顺序非常重要,因为作业(通过=)始终会分配给左侧的变量。

答案 2 :(得分:0)

使用您的代码,做了一些小改动: - 试试这个: -

total = 0
students.each do |key, value|
     total += value
     puts total
end