我试图解决Ruby中一个非常简单的问题。我的目标是使用for循环和.each方法获取以下散列和打印值和键。
my_stocks = { 'Apple' => { 'symbol' => 'AAPL', 'price' => 100 },
'Google' => { 'symbol' => 'GOOG', 'price' => 1150 },
'Tesla' => { 'symbol' => 'TSLA', 'price' => 295 },
'Microsoft' => { 'symbol' => 'MSFT', 'price' => 95},
'Netflix' => { 'symbol' => 'NFLX', 'price' => 300},
'Facebook' => { 'symbol' => 'FB', 'price' => 175},
'Amazon' => { 'symbol' => 'AMZN', 'price' => 1250} }
所以,我正在使用这个定义的方法来打印整个哈希:
def execute_exercise(my_stocks)
for i, j in my_stocks
puts j
end
end
显然,这成功了。我接下来要做的是,使用for循环只打印超过500的键的值。
我提出的每个解决方案都会在Ruby中引发错误:
rbtest.rb:18:in `>': no implicit conversion of Fixnum into Hash (TypeError)
from rbtest.rb:18:in `block in execute_exercise'
from rbtest.rb:18:in `each'
from rbtest.rb:18:in `execute_exercise'
from rbtest.rb:25:in `<main>'
我做的尝试是:
my_stocks.each {|symbol,price| puts symbol if price > 500}
for q, e in my_stocks.to_i < 500
puts e
end
我希望从哈希中打印出值,但很显然我在这里遗漏了一些东西。我不能在没有.to_h
的情况下将fixnum转换为哈希,但这样做是否有效?我只是误解了循环还是别的什么?
你要求Ruby在这里做得太多了:
for q, e in my_stocks.to_i < 500
这真的没有任何意义。 for
迭代一个容器。 to_i
返回一个整数。 x.to_i < n
返回一个布尔值。你不能迭代一个布尔值。另外,my_stocks
是一个哈希,它没有做to_i
,所以这整行不是Ruby可以理解的东西。
而是以不同的方式思考问题。 Ruby的方法是将其分解为几个步骤。首先,查找特定值以上的所有股票:
my_stocks.select do |_name, data|
data['price'] > 500
end.each do |name, data|
# ... print or whatever
end
这里采用Enumerable来帮助解决问题分两个阶段。 select
过滤,each
迭代。在Ruby中,for
并没有真正使用,它真的不是最好的工具。
Enumerable的真正威力在于您可以将一个操作链接到下一个操作。对于不熟悉Ruby的人来说,end.each
可能看起来很奇怪,但这确实是Ruby如何轻松处理复杂的操作。
例如,按价格(从最高到最低)进行过滤和排序只是一个小修改:
my_stocks.select do |_name, data|
data['price'] > 500
end.sort_by do |_name, data|
-data['price']
end.each do |name, data|
# ... print or whatever
end
-data['price']
部分是一种避免以后必须反转值的简单方法。通常它按递增顺序排序,因此当最高值变为最低值时,反转排序会逐渐减少。
您可以像这样使用循环语法,但只需使用“next”跳过价格不符合您要求的项目的迭代:
for q, e in my_stocks
next unless e['price'] > 500
puts q
puts e
end
这将输出:
Google
{"symbol"=>"GOOG", "price"=>1150}
Amazon
{"symbol"=>"AMZN", "price"=>1250}