Ruby中优雅的环埃尔辛

Ruby中优雅的环埃尔辛,ruby,loops,Ruby,Loops,我必须编写一个Ruby方法: 遍历数组,如果其中一个元素匹配某个条件,则执行Foo 如果没有一个数组元素与条件匹配,则执行Bar操作 在任何其他语言中,我都会在进入循环之前设置一个布尔变量,并在执行Foo操作时进行切换。该变量的值将告诉我是否需要禁用。但这感觉毫无疑问是不雅的。有人能提出更好的办法吗 编辑一些非常好的答案,但由于我应该提到的一个细节,它们不太有效。Foo对匹配条件的数组元素执行的操作。此外,保证最多有一个元素与条件匹配。您可以这样做: if array.any? { |elem|

我必须编写一个Ruby方法:

  • 遍历数组,如果其中一个元素匹配某个条件,则执行Foo

  • 如果没有一个数组元素与条件匹配,则执行Bar操作

  • 在任何其他语言中,我都会在进入循环之前设置一个布尔变量,并在执行Foo操作时进行切换。该变量的值将告诉我是否需要禁用。但这感觉毫无疑问是不雅的。有人能提出更好的办法吗


    编辑一些非常好的答案,但由于我应该提到的一个细节,它们不太有效。Foo对匹配条件的数组元素执行的操作。此外,保证最多有一个元素与条件匹配。

    您可以这样做:

    if array.any? { |elem| elem.condition }
      foo
    else
      bar
    end
    
    从,
    可枚举#any
    执行以下操作:

    将集合的每个元素传递给给定的块。如果块返回的值不是false或nil,则该方法将返回true


    有没有匹配的项目?如果是,那么做一些事情,不要涉及匹配的项目

    if items.any? { |item| item.totally_awesome? }
      foo "we're totally awesome!"
    else
      bar "not awesome :("
    end
    
    awesome_item = items.find { |item| item.totally_awesome? }
    if awesome_item
      foo "#{awesome_item.name} is totally awesome!"
    else
      bar "no items are awesome :("
    end
    
    抓取第一个匹配项。如果存在,则对匹配项执行操作

    if items.any? { |item| item.totally_awesome? }
      foo "we're totally awesome!"
    else
      bar "not awesome :("
    end
    
    awesome_item = items.find { |item| item.totally_awesome? }
    if awesome_item
      foo "#{awesome_item.name} is totally awesome!"
    else
      bar "no items are awesome :("
    end
    
    抓取所有匹配的项目。如果数组中有任何内容,则对所有匹配项执行操作

    awesome_items = items.find_all { |item| item.totally_awesome? }
    if awesome_items.any?
      foo "#{awesome_items.size} totally awesome items!"
    else
      bar "no items are awesome :("
    end
    

    编辑:根据新问题标准进行修改

    found_index = nil
    my_array.each_with_index.detect { |elem, i| elem.condition? && found_index = i }
    if found_index.nil?
      do_not_found_case
    else
      my_array[found_index] = some_conversion(elem)
    end
    
    这并不漂亮,但它完成了任务,在第一场比赛中仍然短路。

    你想要的是

    idx = the_array.index { |i| conditional(i) }
    if idx
      modify_object(the_array[idx])
    else
      no_matches
    end
    
    例:


    感谢所有试图回答这个问题的人。你们中没有人提供了我认为合适的答案,但你们都迫使我思考如何用Ruby方式做事(这是本练习的重点!),并帮助我得出了以下答案:

    我需要利用Ruby中的迭代器只是方法这一事实。所有方法都返回一个值,而且(奇怪的是)
    每个方法都返回一个有用的值。如果迭代完成,它将返回您正在迭代的集合;如果使用
    break
    提前终止迭代,它将返回
    nil
    (或可选参数)

    因此,在布尔上下文中,如果循环完成,则整个循环为
    true
    ;如果循环中断,则整个循环为
    false
    。因此

    bar if array.each do |element|
      if fooable(element) then
        foo(element)
        break
      end
    end
    

    按照我的说法,这是一个很好的答案,但它不能解释我遗漏的一个事实:Foo涉及更改与条件匹配的数组元素。我想不出一个真正简短、优雅、红宝石般但仍然有效的方法来做到这一点。更详细但有效的回退方法是标记是否进行了更改。我将使用解决方案进行编辑,但我很高兴看到更好的解决方案。@SporkInventor下面的更简洁。您需要展示您为解决此问题所写的内容。否则你好像在寻找答案。@theTinMan我什么都没写。在任何情况下,这都不是一段很大的代码。我已经掌握了足够的知识来编写代码,我只是想学着像一个Ruby人一样思考。你应该接受@Alex Wayne的答案。它解决了你问题的第二部分。@louism Alex的回答有其优点,但我有一个更好的。我有空的时候会把它贴出来的,很好。如果我没有找到一种方法来处理它们的话,我会接受它。在我看来,这肯定比有标记的答案好得多,而且肯定比好的Ruby代码更地道?因为它使用find而不是each?但这意味着它需要两个步骤来完成一件事,而每个步骤都是一个步骤。@IsaacRabinovitch使用,而不是,yes。请注意,文档中没有提到每个
    的返回值,但是查找的返回值非常清楚。这也更简洁易读。它甚至可以作为一个单行程序
    (element=array.find{| x | x.passes_requirements?})来完成?element.foo!:bar
    还是会好得多。我觉得这与Ruby的功能正好相反。我不会记下它,我只是觉得你应该把记号移到别处。我不太在乎你是否记下我。我很在乎你没有解释你为什么要这样做。你还有其他几个答案,这些答案显示的代码更惯用、更清晰,并且按照预期的方式使用库函数(例如,不依赖每个的返回值,或者在有其他标准函数可用的迭代中,
    中断
    ),他们工作。然而,你已经决定给自己打勾,你还没有解释为什么你的答案更接近于“Ruby方式”,这显然是要点,或者为什么他们的答案“不合适”。我使用的行为被记录在案。我同意我的评价是主观的,但它比你的火焰诱饵更具建设性。在你的问题中,你有“毫不夸张的不雅”,在你的回答中,你有“Ruby方式(这是本练习的重点!),所以我想我可以清楚地给出我的观点,什么是写Ruby的或多或少的惯用方式。没有悲剧,只有我的正确意见。