【问题标题】:Printing Values in a Hash using the conditional operator "for" and Ruby's .each使用条件运算符“for”和 Ruby 的 .each 在哈希中打印值
【发布时间】:2019-09-18 14:46:24
【问题描述】:

我正在尝试解决 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 转换为哈希,但这是否有效?我只是误解了 for 循环还是其他原因?

【问题讨论】:

  • 我们没有像其他语言那样的“守卫”,而是我们通常使用链式方法处理迭代。真正简单的方法是你的第一个代码puts j if j[:price] &gt; 500

标签: ruby loops hash


【解决方案1】:

你在这里要求 Ruby 一次做太多事情:

for q, e in my_stocks.to_i < 500

这真的没有任何意义。 for 遍历容器。 to_i 返回一个整数。 x.to_i &lt; n 返回一个布尔值。你不能迭代一个布尔值。另外,my_stocks 是一个 Hash,它不做 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 的真正强大之处在于您可以将一个操作直接链接到下一个操作。 end.each 对于不熟悉 Ruby 的人来说可能看起来很奇怪,但这确实是 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'] 部分是避免以后必须反转值的简单方法。通常它是按升序排序的,所以倒序排序是随着最高值变为最低值而递减。

【讨论】:

  • 我明白了。所以,虽然我习惯于在其他语言中使用for 循环,但使用提供的.each 方法更容易使用Ruby?所以do 定义要收集哪些参数,data 参数指定要搜索的哈希区域?您假设end.sortend.each 对我来说看起来很陌生也是正确的。怎么可能做到这一点?
  • 请参阅ruby-doc.com/core-2.6.2/Enumerable.html 上的文档作为答案参考。但是这些方法按照它们的名称所暗示的那样做,并且可以对可枚举的对象(即哈希或数组)进行操作。有更多笨拙的方法来执行循环,但这更像是您的用例的 Ruby 约定。
  • 其他语言使用for,因为这就是他们所拥有的一切。一些像 JavaScript 的混合:for (...) { ... }array.forEach(function(e) { ... }),你可以选择你喜欢的。在 Ruby 中,for 几乎毫无用处,因为 Enumerable 做了它可以做的所有事情,而且远不止如此,如果有一天它从语言中删除,我不确定是否有人会注意到。 .each 有一个接收单个参数的块,即被迭代的元素,但也有 each_with_index(元素,索引)和 each_with_object(元素,任意对象)作为两个示例。
【解决方案2】:

您可以使用这样的循环语法,但只需使用“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}

【讨论】:

    猜你喜欢
    • 2013-09-30
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 2014-11-30
    • 2015-05-29
    • 2014-07-21
    相关资源
    最近更新 更多