我正在用代码重写这个问题:
many = 1000
# An expensive method.
#
# It returns some data or nil if no result is available.
expensive_method = lambda do
rand(5) == 0 ? nil : "foo"
end
# Now, let's collect some data and stop collecting when no more data is
# available.
# This is concise but doesn't work.
collection = many.times.map do
expensive_method.call || break
end
puts collection.is_a? Array # false
# This is less concise but works.
collection = []
many.times do
collection << (expensive_method.call || break)
end
puts collection.is_a? Array # true
# My inner Rubyist ponders: Is it possible to accomplish this more concisely
# using map?
发布于 2016-06-24 02:36:21
不要直接使用map
,而是构建您自己的集合,然后使用break
返回值的事实提前中止:
result =
[0, 1, 2, 1, 0].each_with_object([]) { |val, accumulator|
if val < 2
accumulator << val
else
break accumulator
end
}
result # => [0, 1]
如果我们只做break
(而不是break accumulator
),那么nil
将被隐式返回,result
将被设置为nil
。
这种解决方案的优点是只分配一个累加器阵列,并且只需要循环一次。
发布于 2011-07-13 15:02:44
当然,在Ruby中实现这一点的唯一方法似乎是使用filter类型的方法,然后将结果传递给map。我不确定这在1.8中是否有效,但在1.9中您可以:
[0,1,2,1,0].take_while {|val| val < 2}.map(&:some_function)
或者在times
示例中
3.times.take_while {|count| count <= 1 } #=> [0,1]
发布于 2011-07-13 02:12:22
irb(main):011:0> 3.times.select {|count| count <= 1}
=> [0, 1]
或
irb(main):014:0> 3.times.reject {|count| count > 1}
=> [0, 1]
https://stackoverflow.com/questions/6668008
复制相似问题