【问题标题】:undefined method `each' for true:TrueClass (NoMethodError)未定义的方法“每个”为真:TrueClass(NoMethodError)
【发布时间】:2019-12-13 12:07:46
【问题描述】:

我正在用 Ruby 编写一个 for 循环,它遍历数组的元素,直到没有更多元素要读取或满足某个条件。这是我的实现:

# 'all' is an array

exists = false

for i in all && !exists
  exists = all[i].has_card
end

正如标题所说,我收到了这个运行时错误:

undefined method `each' for true:TrueClass (NoMethodError)

我对 Ruby 还很陌生,但我猜问题是for 循环试图遍历all!exists,即true。我怎样才能按照我想要的方式编写一个?

编辑:如果它作为澄清,这就是我将如何在 C++ 中实现它:

for (int i=0; i<all.size() && !exists; i++) { /*...*/ }

【问题讨论】:

    标签: ruby for-loop nomethoderror


    【解决方案1】:

    首先,嗯。 for 从未使用过;它是红宝石的“湿润”。 :)

    for item in items ... end 由 Ruby 执行,就像您编写 items.each do |item| ... end 一样。 (实际上,Ruby 主义者一开始就是这样写的。)这是相关的;所以等等。

    您的行解析为:

    for i in (all && (!exists))
    

    existsfalse 时,!existstrue。现在,&amp;&amp; 运算符将检查第一个参数是否为真;如果不是,则返回它;如果是,则返回第二个参数。由于all 可能是真的,all &amp;&amp; true 返回第二个参数——真。

    现在请记住,您的行实际上在后台调用了您正在迭代的集合的 each 方法。而你的“收藏”是true——根本不是收藏。你不能迭代true

    如果你不想使用break(这有点不合理,可以引用我的话),你可以使用Enumerable模块中的其他方法。例如:

    all.take_while { |item| !item.has_card }.each do |item|
      # ...
    end
    

    这比break 方法慢一点,因为它将构造一个中间数组,其中仅包含前 N 个没有卡片的项目,稍后将对其进行迭代,但担心它是过早的优化。

    编辑:不幸的是,塞巴斯蒂安删除了他们的答案,该答案具有正确的习语(我可能会比上面的那个更早写,尽管这肯定取决于具体情况),所以我在这里重复一遍:

    all.each do |item|
      break if item.has_card
      # ...
    end
    

    【讨论】:

    • 不。 for(等价于 each仅迭代整个集合。您无法指定附加条件。您可以使用 each以外的函数来执行此操作>,或者有条件地使用break。没有办法纯粹使用for来做你想做的事。Ruby for与C for几乎没有关系,你最好忘记它存在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 2013-04-24
    相关资源
    最近更新 更多