Ruby#选择,但只选择某个数字
Ruby中执行my|u数组之类的操作的最佳方法是什么?选择(n){elem|…},其中Ruby#选择,但只选择某个数字,ruby,select,Ruby,Select,Ruby中执行my|u数组之类的操作的最佳方法是什么?选择(n){elem|…},其中n表示“我只希望n返回元素,并在达到该数字后停止计算”这应该可以做到: my_数组。选择(n){| elem | elem.meets_条件?}。取(n) 但是,这仍将评估所有项目 如果你有一个懒惰的枚举器,你可以用一种更有效的方式 显示了启用此功能的尝试。我想可以使用break或类似于以下内容的老式循环样式来完成断开的循环: n = 5 [1,2,3,4,5,6,7].take_while { |e| n -
n
表示“我只希望n
返回元素,并在达到该数字后停止计算”这应该可以做到:
my_数组。选择(n){| elem | elem.meets_条件?}。取(n)
但是,这仍将评估所有项目
如果你有一个懒惰的枚举器,你可以用一种更有效的方式
显示了启用此功能的尝试。我想可以使用
break
或类似于以下内容的老式循环样式来完成断开的循环:
n = 5
[1,2,3,4,5,6,7].take_while { |e| n -= 1; n >= 0 && e < 7 }
n=5
[1,2,3,4,5,6,7].在{e | n-=1;n>=0和&e<7}时取u
在函数式语言中,这将是递归,但如果没有TCO,它在Ruby中就没有多大意义
更新
正如dbenhur指出的那样,
take_while
是个愚蠢的主意,所以我不知道什么比循环更好。为什么不把它翻过来,在选择之前先做“take”:
这将确保您只对n
项目数进行计算
编辑:
Enumerable::Lazy的计算速度较慢,但如果您的计算比Lazy的计算速度慢,那么您可以使用Ruby 2.0功能:
my_array.lazy.select { |elem| ... }.take(n)
请参阅:如果您使用的是stock 1.8.7或1.9.2,似乎无法避免传统循环
result = []
num_want = 4
i = 0
while (elem = my_array[i]) && my_array.length < num_want
result << elem if elem.some_condition
i += 1
end
result=[]
num_want=4
i=0
while(elem=my_-array[i])&&my_-array.length 结果您可以轻松实现lazy\u select
:
module Enumerable
def lazy_select
Enumerator.new do |yielder|
each do |e|
yielder.yield(e) if yield(e)
end
end
end
end
然后像
(1..10000000000).to_enum.lazy_select{|e| e % 3 == 0}.take(3)
# => [3, 6, 9]
立即执行。您可以创建一个类似可枚举的扩展,该扩展具有所需的selectn语义:
module SelectN
def selectn(n)
out = []
each do |e|
break if n <= 0
if yield e
out << e
n -= 1
end
end
out
end
end
a = (0..9).to_a
a.select{ |e| e%3 == 0 } # [0, 3, 6, 9]
a.extend SelectN
a.selectn(1) { |e| e%3 == 0 } # [0]
a.selectn(3) { |e| e%3 == 0 } # [0, 3, 6]
# for convenience, you could inject this behavior into all Arrays
# the usual caveats about monkey-patching std library behavior applies
class Array; include SelectN; end
(0..9).to_a.selectn(2) { |e| e%3 == 0 } # [0,3]
(0..9).to_a.selectn(99) { |e| e%3 == 0 } # [0,3, 6, 9]
模块选择n
def selectn(n)
out=[]
每个都有|
如果你是对的,那就休息吧,我刚发完帖子就开始思考。我被其他几种语言中的惰性枚举所惯坏,我忘记了那个细节。我更新了我的答案以反映这一点。另请参见。to_enum
的速度非常慢(至少在R1.8中是如此),简单循环的速度要快得多,所以懒惰的东西看起来很不错(除非您想完全重新实现它)。至少这是我试用后的印象。是的,这个懒惰的特性现在只是2.0的一部分。我不确定to|enum会有什么影响,但我可以想象它在1.9.(1..100000000)中会更好一些。to|enum.lazy.select{x | x%3==0}.take(10)。to|a在ruby 2.0中速度非常快,因为它值得。。。我想,成本的高低取决于将特定对象转换为枚举的复杂性。然后,您必须重复该操作,直到获得正确的计数。对于第一次n
之后可能有我想要的项目的情况,这不起作用……因为这与请求的内容无关,您需要先应用选择,然后再取(n)
,事实上,不是反过来。在这种情况下,您确实需要惰性枚举。这并不等同于选择{}。take(n)它将在第一个未通过条件的元素处停止获取。您还可以执行my_array.each,然后在选择num_want元素时中断(功能上完全相同,但更像ruby)
module SelectN
def selectn(n)
out = []
each do |e|
break if n <= 0
if yield e
out << e
n -= 1
end
end
out
end
end
a = (0..9).to_a
a.select{ |e| e%3 == 0 } # [0, 3, 6, 9]
a.extend SelectN
a.selectn(1) { |e| e%3 == 0 } # [0]
a.selectn(3) { |e| e%3 == 0 } # [0, 3, 6]
# for convenience, you could inject this behavior into all Arrays
# the usual caveats about monkey-patching std library behavior applies
class Array; include SelectN; end
(0..9).to_a.selectn(2) { |e| e%3 == 0 } # [0,3]
(0..9).to_a.selectn(99) { |e| e%3 == 0 } # [0,3, 6, 9]