在 ruby 中我们可以做这样的事情:
stuff_in_trash.detect(&:eatable?)
=> :pack_of_peanuts
stuff_in_trash.detect(&:drinkable?)
=> nil
Run Code Online (Sandbox Code Playgroud)
但是,如果我们对块第一次为真时的值感兴趣,而不是块取真值的第一个项目,该怎么办?
也就是转换下面的代码:
def try_to_make_artwork_from(enumerable)
enumerable.each do |item|
result = make_artwork_from item
return result if result
end
nil
end
Run Code Online (Sandbox Code Playgroud)
对于类似的事情:
def try_to_make_artwork_from(enumerable)
enumerable.try_with { |item| make_artwork_from item }
end
Run Code Online (Sandbox Code Playgroud)
初始代码中需要的内容是:
nil如果该块从未采用真值,则返回;make_artwork_from再次调用(假设它不能保证下次调用它时返回相同的结果)。不太理想的是,使用了result三次,但与故事无关。
编辑:抱歉,最初的实现是不正确的,它需要在nil块值从来不为真的情况下返回。
enumerable.lazy.map(&:block).detect(&:itself)
Run Code Online (Sandbox Code Playgroud)
可以完成这项工作,但这是最简单的方法吗?each与简单地使用并缓存值相比,它是否有效?
\n\n\n它可以完成工作,但这是最简单的方法吗?与简单地使用each并缓存值相比,它是否有效?
\n
我们可以定义这个方法:
\n\ndef first_truthy_block(enumerable, &block)\n enumerable.lazy.map(&block).find(&:itself)\nend\nRun Code Online (Sandbox Code Playgroud)\n\n在这里行动:
\n\narray = [0,1,2,3,4,:x5,\'abc\']\n\nputs first_truthy_block(array) { |x|\n if x ** 2 > 10 then\n "ARTWORK with #{x}!!!"\n end\n} \n#=> ARTWORK with 4!!!\nRun Code Online (Sandbox Code Playgroud)\n\n能更简单一点吗?
\n\nenumerable是需要的,它是您正在处理的对象。lazy需要时,它不会尽快停止,并且会抛出异常:x5**2。使用标准Enumerable方法,我不认为它会变得更简单。
它比你的each方法慢。它基本上做同样的事情,并且应该具有相同的复杂性,但它确实使用更多的方法调用并创建更多的对象:
require \'fruity\'\n\ndef first_truthy_block_lazy(enumerable, &block)\n enumerable.lazy.map(&block).find(&:itself)\nend\n\ndef first_truthy_block_each(enumerable, &block)\n enumerable.each do |item|\n result = block.call(item)\n return result if result\n end\n nil\nend\n\nbig_array = Array.new(10_000){rand(4)} + [5] + Array.new(10_000){rand(20)} + [:x, :y, \'z\']\n\ncompare do\n _lazy_map do\n first_truthy_block_lazy(big_array) { |x|\n if x ** 2 > 10 then\n "ARTWORK with #{x}!!!"\n end\n }\n end\n\n _each do \n first_truthy_block_each(big_array) { |x|\n if x ** 2 > 10 then\n "ARTWORK with #{x}!!!"\n end\n }\n end\nend\nRun Code Online (Sandbox Code Playgroud)\n\n果味回报:
\n\nRunning each test once. Test will take about 1 second.\n_each is faster than _lazy_map by 3x \xc2\xb1 0.1\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2039 次 |
| 最近记录: |