gpt4 book ai didi

ruby 可枚举 : first truthy value of a block

转载 作者:数据小太阳 更新时间:2023-10-29 07:55:05 26 4
gpt4 key购买 nike

在 ruby​​ 中我们可以这样做:

stuff_in_trash.detect(&:eatable?)
=> :pack_of_peanuts

stuff_in_trash.detect(&:drinkable?)
=> nil

但是,如果我们对 block 第一次为真时的值感兴趣,而不是 block 为其取真值的第一个项目感兴趣怎么办?

也就是转换如下代码:

def try_to_make_artwork_from(enumerable)
enumerable.each do |item|
result = make_artwork_from item
return result if result
end
nil
end

类似于:

def try_to_make_artwork_from(enumerable)
enumerable.try_with { |item| make_artwork_from item }
end

初始代码中需要的是:

  1. 如果 block 从不取真值,它返回nil
  2. 它在第一次为真时返回区 block 的值;
  3. 找到第一个匹配项后停止;
  4. 它不会再次调用 make_artwork_from(我们可以说它不能保证在您下次调用时返回相同的结果)。

不太理想的是,使用了三次result,但它与故事无关。

编辑:抱歉,最初的实现是不正确的,它需要返回 nil 以防 block 值永远不为真。

enumerable.lazy.map(&:block).detect(&:itself)

完成这项工作,但这是最简单的方法吗?与简单地使用 each 并缓存值相比,它是否有效?

最佳答案

it does the job, but is the simplest way? Is it efficient compare to simply using a each and caching the value?

最简单的方法?

我们可以定义这个方法:

def first_truthy_block(enumerable, &block)
enumerable.lazy.map(&block).find(&:itself)
end

实际操作:

array = [0,1,2,3,4,:x5,'abc']

puts first_truthy_block(array) { |x|
if x ** 2 > 10 then
"ARTWORK with #{x}!!!"
end
}
#=> ARTWORK with 4!!!

可以更简单吗?

  • enumerable 是必需的,它是您正在处理的对象。
  • 需要
  • lazy,它不会尽快停止,并会抛出 :x5**2 的异常。
  • 需要 map ,你需要对你的元素应用一些方法
  • 需要从您的可枚举中最多提取一个值

使用标准的 Enumerable 方法,我看不出它还能更简单。

效率高吗?

它比您的 each 方法慢。它基本上做同样的事情,应该具有相同的复杂性,但它确实使用了更多的方法调用并创建了更多的对象:

require 'fruity'

def first_truthy_block_lazy(enumerable, &block)
enumerable.lazy.map(&block).find(&:itself)
end

def first_truthy_block_each(enumerable, &block)
enumerable.each do |item|
result = block.call(item)
return result if result
end
nil
end

big_array = Array.new(10_000){rand(4)} + [5] + Array.new(10_000){rand(20)} + [:x, :y, 'z']

compare do
_lazy_map do
first_truthy_block_lazy(big_array) { |x|
if x ** 2 > 10 then
"ARTWORK with #{x}!!!"
end
}
end

_each do
first_truthy_block_each(big_array) { |x|
if x ** 2 > 10 then
"ARTWORK with #{x}!!!"
end
}
end
end

果味返回:

Running each test once. Test will take about 1 second.
_each is faster than _lazy_map by 3x ± 0.1

关于 ruby 可枚举 : first truthy value of a block,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41571054/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com